How do I make a Matlab plot fill the whole page? - matlab

I want to make a plot in Matlab which is twice as tall as it is long. I tried following the advice of this question using Position and PaperPositionMode, like so:
figure
set(gcf,'PaperPositionMode','auto');
set(gcf, 'Position', [0 0 100 200]);
barh(1:20);
print('test', '-dpng');
Annoyingly, this resizes the paper size but not the plot, as below.
Is there any way to make a graph with specified width and height? I'm running this on a headless server so clicking and dragging, or any other GUI-specific solutions, aren't an option. Obviously I don't actually want a 100x200 plot, I just wanted to make the figure small enough to fit nicely into the question.

You might try setting the paper size and units. There's a similar question on Mathworks. Relevant content:
set(0,'defaultfigurepaperunits','inches');
set(0,'defaultfigurepaperorientation','landscape');
set(0,'defaultfigurepapersize',[8.5 11]);
set(0,'defaultfigurepaperposition',[.25 .25 [8.5 11]-0.5]);
where set(0, ...) sets the root graphics system values. You could also use your figure instead. Hope this helps.

Alternative approach reference the documentation for figure(). Uses the units & outerposition properties.
figure('units','normalized','outerposition',[0 0 1 1])
See also the position property for another approach.

Related

Matlab: create lines with equal physical length along each axis

I want to make scale bars with ticks, and I want the ticks on the X and Y bars to have the same physical length, regardless of the relative lengths, dimensions, or "modes" of the axes (at least at the time the ticks are created). I was hoping that daspect() would give me the information I need for this, but daspect() seems to be mostly useless for interrogating aspect ratio. For instance, if I generate a plot that Matlab gives an XLim of [0 3.5] and a YLim of [0 1], then daspect() gives [3.5 1 ...] regardless of how I have the figure sized on the screen. That's obviously not accurate or helpful. Is there another function, or maybe a way to make daspect() give useful information without manipulating the plot?
daspect() returns garbage on a typical plot. It's because of the stretch-to-fill feature, which distorts the plot to fill up the figure space, rendering the values in DataAspectRatio inaccurate. Instructions for turning off stretch-to-fill can be found here.
I also found a workaround if you want to leave stretch-to-fit on, which is to temporarily set PlotBoxAspectRatioMode to 'manual,' which has the effect of changing the value of DataAspectRatio to match what is on screen.
figure;plot(0.1:0.1:pi,sin(0.1:0.1:pi))
pbaspect manual
val = daspect
pbaspect auto
Or a safer way to do it if you want a generally useful script (e.g. in case PlotBoxAspectRatioMode is already manual and you don't want to change that) would be:
pbaspectMode = get(gca,'PlotBoxAspectRatioMode');
pbaspect manual;
val = daspect;
set(gca,'PlotBoxAspectRatioMode',pbaspectMode);
I'm not sure whether this will have any intermittent or pernicious side effects, however.
According to The Mathworks support:
The technique of setting bpaspect to manual and then back may be "safe" (although I wouldn't be surprised if there are side effects), but a better way is to divide:
real_daspect = daspect./pbaspect;

How to draw good looking arrows in Matlab?

I have been trying to draw arrows in Matlab in my figure but they all look terrible.
Also, I want my arrowhead to be a solid triangle, not a V.
I tried using the packages available on the Matlab File Exchange: arrow, arrows, arrows3, and probably at least one other one.
I even tried manually creating an arrow in the Matlab figure editor, but when I adjust the line width, the arrow looks like this:
I used the annotation command to create the arrow above:
annotation(gcf,'arrow',[0.621875 0.457916666666667],...
[0.205421152030217 0.40755429650614],...
'HeadLength',4,'LineWidth',5);
Here's the result trying to use the arrow package available here: Arrow.m (notice how the bottom arrow head is not perpendicular to the line:
I even tried the following and here is the result below (notice the terrible looking arrowhead):
figure
plot(1:10, 1:10)
annotation(gcf,'arrow',[0.621875 0.457916666666667],...
[0.205421152030217 0.40755429650614],...
'HeadLength',4,'LineWidth',5);
Vector graphics is hard. Though Matlab's typography is just as bad, but here's a simplistic text-based solution (I refuse to do this sort of annotation in Matlab any more):
figure
plot(1:10, 1:10)
text(5,4,'\rightarrow','FontSize',54,'Rotation',135,...
'HorizontalAlignment','center');
which yields a figure like this
Note that I have used '\leftarrow' because it points in the direction of zero degrees, which makes doing math in my head easier. This is no canned solution, you'll still need to fiddle with position to overcome the fact that Matlab is aligning this as text (see the 'Extent' and 'Margin' properties). Not surprisingly, you may see small glitches. The LaTeX interpreter can be used to obtain a different style arrow head:
text(5,4,'$\rightarrow$','FontSize',54,'Rotation',135,...
'HorizontalAlignment','center','Interpreter','latex');
I don't get the small glitches with this option, but the arrows look different (there are likely other LaTeX arrow styles that could be substituted). Changing the font may also have an effect and there are certainly other text-based arrows that could be used. More details on adding arrows can be found in this article from The MathWorks.
Another solution is to use the open-source Waterloo graphics - a library that addresses this by providing a pure Java library of 2D graphics functions that can easily be integrated in Matlab. See some examples here...
For example, try this code (after properly installing waterloo)
f = GXFigure();
x = -5:0.1:5;
gr1 = gxgca();
a1 = line(gr1, x, cos(x), 'LineSpec','-ob');
b1 = line(gr1, x, sin(x), 'LineSpec','-sg');
annotation(gr1,'arrow',[0.1 0.1],[0.4 0.4],'HeadLength',0.2,'HeadWidth', 0.5, 'LineWidth',2);
gr1.getObject().getView().autoScale();
Having worked with Matlab for more than 10 years and seeing almost zero progress in the quality of the plots (anti-aliased output to bitmap, decent looking eps-files, ...), I decided that my long time solution will be here. Some examples of decent looking arrows here, more beautiful graphs here. Unfortunately, some of the toolboxes prevent me from going completely to numpy/scipy/matplotlib. I know this is more of a rant than an answer, but that is my solution ...
Using quiver or quiver3 for 3-D plots will certainly look better than the that last arrow you made using annotation. I'm not sure it will look much better than the ones you made using the Arrow.m package though. It's possible to change the stlyes on quiver as well if you want.
I resorted to installing InkScape and drawing arrows in there. Nothing beat the simplicity and quality.
InkScape Website
When line-based arrows fail, you can always try patch-based ones:
xArrow = [0 1 1 1.2 1 1 0]; % X-coords of arrow edge points
yArrow = [-0.1 -0.1 -0.2 0 0.2 0.1 0.1]; % Y-coords of arrow edge points
hArrow = fill(xArrow,yArrow, [1 0 0]); % Plot a red arrow
axis equal % Set axis tick marks to be equal
Although more work, you can potentially parameterize the above into a function that takes a number of arguments for adjusting the scaling, aspect ratio, rotation, and position of the arrow. You can even adjust the color, edge line color, and alpha transparency.
This sort of idea appears to have been implemented by François Beauducel in his File Exchange submission ARROWS: generalized 2-D arrows plot.
There is now the DaVinci Draw toolbox (full disclosure: I wrote/sell the toolbox), which uses low-level Matlab commands like plot() and patch() to draw mid-level shapes like arrows. Example syntax:
davinci( 'arrow', 'X', [0 10], ...
'Y', [0 2], ...
'Shaft.Width', 1, ...
'Head.Length', 2.5, ...
'Color', 'w', ...
'EdgeColor', 'k', ...
'LineWidth', 2.5 )
From the documentation:

MatLab: set function arguments

I have found this line of MatLab code on the internet that displays a figure window in fullscreen:
set(figure(1),'Units','Normalized','OuterPosition',[0 0 1 1])
It works perfectly, and my question isn't regarding any problems here; it is instead regarding some explanation of it. You see, I don't understand the code line. Can anybody explain to me the arguments in this?
figure(1) is my figure handler - the current figure window - I understand that. But the rest of the arguments are confusing me. What does Units, Normalized and OuterPosition do, and what is the vector [0 0 1 1] specifying?
I have found the code line here: source (see the latest answer).
I'm having big trouble decrypting the help info provided by the help set command in MatLab. The MathWorks website weren't better and had no exampls of this that I could find.
Does anyone have some explanation or do you know where to find some understandable info?
Note
Alternatively, does anyone know of a better method for displaying a plot window or figure window in fullscreen? I need to be able to understand the method, or else I can't use it.
The arguments are considered "property-value pairs".
The first pair, 'Units', 'Normalized', tells the figure that you'll be giving it normalized values (between 0 and 1) rather than other options - pixels or inches, for example.
The second pair, 'OuterPosition', [0 0 1 1], tells it that you want to position the figure with the lower left (outside) corner at (0,0) with a width and height of (1,1). Since you indicated that units are normalized, (0,0) means the lower left corner of the screen, and (1,1) means the full height and width of the screen.
Property-value pairs allows you to pass in some relevant information but not other stuff for which the default is fine, and makes the order in which you do so flexible. It is a widely-used system in MATLAB.

making axes distinct from other grid

Does anyone know how to make x-axis and y-axis look a bit bolder or somehow distinct from other grids?
Somehow I want it to look like this
The stupidest thing I can think of is drawing a line with LineWidth = 2
figure();
plot([0 0],[-200 200],'LineWidth',2,'Color',[0 0 0])
hold on;plot([-200 200],[0 0],'LineWidth',2,'Color',[0 0 0])
Though it has some obvious disadvantages, like that it ends at some place.
Check out hline and vline from the MATLAB File Exchange. It will let you draw horizontal and vertical lines at any given point and extend those lines to infinity (so redoing axes will still keep the lines drawn all the away across your plot). If you need to draw to specific handles, here's an advanced hline/vline.

How to make ticks equidistant in MATLAB

I have the plot shown below:
Now the problem is that I need to make the fonts large at the same time, I need to make them clear (disjoint). I do not care about the ratio of spaces between ticks. one solution is to have the spaces equidistant so that I can read the tick labels carefully. Any Idea how i can do that?
Following Yoda's comments I surely do get a better look.
I do not know how to get the aspect ratio but I use the following code
figure('Units', 'pixels', ...
'Position', [100 100 500 375]);
The font size is 16 and I set the Axis as:
axis([-1 1 0 100])
It would be more helpful if you also told us what the aspect ratio is and what font-size you're using. If I try to reproduce it, I get a reasonable looking plot where the labels are easy to read at a fontsize of 16 or 18.
Now, moving the tick marks around or intentionally labeling in a different position can lead to lot more problems in interpretation (for one, the data point will no longer align with the tick) and I wouldn't suggest that approach. In your case however, is 0.33 equivalent to 1/3? If so, you could use 1/2 and 1/3 and save some space. You can set it with
set(gca,'xtick',[-1,-0.5,-0.33,0,0.33,0.5,1],...
'xticklabel',{'-1','-1/2','-1/3','0','1/3','1/2','1'},
and it should look like this: