In a m-file, I am plotting 16 different types of plots (not in a loop). Is it possible to set the following properties of all the plots by writing only once:
set(gca,'linewidth',1,'fontsize',12);
set([xh, yh, th],'fontsize',12);
It turns out that the answer is yes, which can be easily checked e.g. using this code
figure
xh = gca;
figure
yh = gca;
set([xh, yh], 'fontsize', 12, 'linewidth', 1);
Note that the 'linewidth' property of an axes applies to the lines that make up the axes, not to any lines plotted into it. If you want to change their properties, you have to either collect the handles of all the line objects, or search for line objects later using
lh = findobj(0, 'Type', 'line');
set(lh, 'linewidth', 1)
Here '0' refers to the root object, of which all figures are children.
You can change default plotting parameters:
set(0,'DefaultLineLineWidth',1);
set(0,'DefaultAxesFontSize', 12);
set(0,'DefaultTextFontSize', 12);
Yes, it is meant to be "LineLine", it's to distinguish it from DefaultPatchLineWidth. Once you change these, it will only affect new figure windows; if you have already created the plots, use the answer given by A. Donda.
Related
I would like to plot 66 datasets and show their legends. Unfortunately, according to the MathWorks Support Team, MATLAB legends are limited by default to 50 entries.
I tried the workaround they suggested that involves making another axes in the plot, copying the previous data, and then hiding the new axes, but I couldn't get it to work (the new axes only shows 1 additional variable from the 16 that are left), and so I'm stuck.
Are there any other ways to display more than 50 legend entries?
As implied by Cris's comment, it's likely that your plot is going to be very unclear - if you need 50+ legend entries then you've got 50+ different line styles, which is pretty crazy from a usability perspective.
That aside, you can achieve an unrestricted legend using the gridLegend FileExchange submission.
% Plot some dummy data, 60 series with various markers / lines
ms = {'*','+','.','d','s','o'};
ls = {'--','-',':','-.'};
x = linspace( 0, 10, 100 ).';
figure(); hold on;
for ii = 1:60;
y = sin(x+ii) + ii + rand(100,1)/2;
p(ii) = plot( x, y, ms{randi(6)}, 'linestyle', ls{randi(4)} );
end
% Call the legend
gridLegend( p );
Output:
I ran into this problem myself and found an undocumented feature that can help—the 'LimitMaxLegendEntries' property of Legend ('matlab.graphics.illustration.Legend') objects. Here's an example:
hF = figure();
hAx = axes(hF);
plot(hAx, magic(100));
hL = legend(hAx, '-DynamicLegend');
set(hL, 'LimitMaxLegendEntries', false, 'NumColumns', 3);
Which results in:
Tested on R2020a.
P.S.
While I agree that these likely way too many legend entries to be useful, I believe one should have the freedom to shoot themselves in the foot.
A solution suggested by Eric Sargent (TMW Staff) is to pass the plot handles to the legend command:
p = plot(magic(100));
legend(p);
Note that in this case, the axes are not determined by gca, but instead using ancestor(p, 'axes') (so there's no need to specify the axes handle when calling legend). Moreover, specifying an axes handle makes this solution stop working!
I use plotyy to put two plots in one graph:
f = figure('Color','white');
[ax,p1,p2] = plotyy(xx, yy1, xx, yy2);
ylabel(ax(1),'Phase','FontSize',18);
ylabel(ax(2),'Spectrum','FontSize',18);
set(ax,{'ycolor'},{'k';'k'});
set(p1,'LineWidth',2,'Color',[0.4940,0.1840,0.5560]);
set(p2,'LineWidth',2,'Color','red');
xlabel(ax(1),['Frequency [THz]'],'FontSize',18);
set(ax,'FontSize',14)
Figure is displayed perfectly, but when I try to save it as fig something like misaligned boxes appears.
I tried to use linkaxes, but with no result.
plotyy has been one of my favorite MATLAB functions to love to hate. It's a really useful function that I always seem to run into bugs with, to the point where I've completely stopped using it in favor of just stacking two (or more) axes objects and plotting to them separately. You can then set the Position property of the 'sub' axes to the same as your primary axes and they will stack nicely.
A functional example:
xx = linspace(-15,15,100);
yy1 = sin(xx);
yy2 = cos(xx);
f = figure('Color','white');
ax(1) = axes('Parent', f);
ax(2) = axes('Parent', f, 'Color', 'none', 'XTick', [], 'YAxisLocation', 'right');
p1 = plot(ax(1), xx, yy1);
hold(ax(2), 'on'); % Hold to preserve our axes properties set above
p2 = plot(ax(2), xx, yy2);
hold(ax(2), 'off');
ylabel(ax(1),'Phase','FontSize',18);
ylabel(ax(2),'Spectrum','FontSize',18);
set(ax,{'ycolor'},{'k';'k'});
set(p1,'LineWidth',2,'Color',[0.4940,0.1840,0.5560]);
set(p2,'LineWidth',2,'Color','red');
xlabel(ax(1),'Frequency [THz]','FontSize',18);
set(ax,'FontSize',14)
set(ax, 'ActivePositionProperty', 'position'); % Resize based on position rather than outerposition
set(ax(2), 'Position', get(ax(1), 'Position')); % Set last to account for any annotation changes
Along with stacking the axes you will also note that I have set the ActivePositionProperty to position (rather than outerposition). MATLAB resizes axes automatically when the Units property is set to Normalized, and it seems like this is the main spot where the issue is arising. On resizing, MATLAB also modifies the OuterPosition value for the second axes, causing it to resize the plot portion. The difference is small, [0 0 1 1] vs. [0 0.0371 1.0000 0.9599] in my case, but the effect is obviously very pronounced. You can use get and set to fix this, but you'll have to do it on every resize which is fairly annoying. The alternative is to resize based on the Position, which seems to alleviate the issue and is a tweak present in the R2015b implementation of plotyy. This also fixes plotyy except for cases where the window is very small, so I have left my answer with the more generic approach.
I tried creating a plot with two YAxis like this:
x=linspace(0,20);
y1=linspace(10,10);
y2=x.^2;
y3=y2-y1;
[hAx,hLine1,hLine2]=plotyy([x',x'],[y1',y2'],x,y3);
Now i have two problem with this code:
I can change the Linestyles of the two hLines using hLine1.LineStyle = ':'; for example, but i can not change the styles of the two lines, that hLine1 consists of. Does anyone know how to do this?
I can't use hLine2.YLim = [0 100] to manually adjust the y-limits shown on the 2nd y-axis.
After I couldn't solve the problem using the plotyy, I searched the MATLAB documentation and found another way of implementing my plot, which I thought might be easier to handle:
x=linspace(0,20);
y1=linspace(10,10);
y2=x.^2;
y3=y2-y1;
figure
hold on;
line(x,y1,'Color','r')
line(x,y2,'Color','y')
ax1 = gca;
ax2 = axes('Position',ax1.Position,'YAxisLocation','right');
line(x,y3,'Parent',ax2,'Color','b')
The problem here is, that it doesn't even show the first and the second line, but only the third and i don't know why. I would prefer getting the problem solved using the plotyy, but if that's not possible I would appreciate a solution for the 2nd piece of code as well.
I think you haven't noticed that the outputs of plotyy are arrays of objects, and not single objects.
x=linspace(0,20);
y1=linspace(10,10);
y2=x.^2;
y3=y2-y1;
[hAx,hLine1,hLine2]=plotyy([x',x'],[y1',y2'],x,y3);
hLine1(1).LineStyle = '--';
hLine1(2).LineStyle = ':';
% either this
ylim( hAx(2), [0 110] );
% or alternatively
f=gcf; ylim( f.Children(2), [0 110] );
You're not seeing the first two lines because axes backgrounds are white by default. Setting the Color property of the second axes object to 'none' should give you what you're looking for:
x=linspace(0,20);
y1=linspace(10,10);
y2=x.^2;
y3=y2-y1;
figure
hold on;
line(x,y1,'Color','r')
line(x,y2,'Color','y')
ax1 = gca;
ax2 = axes('Position',ax1.Position,'YAxisLocation','right', 'Color', 'none');
line(x,y3,'Parent',ax2,'Color','b')
EDIT: I'd also recommend checking out linkaxes if you're going to be zooming/panning your axes and want to keep some or all of the axes synchronized.
Please, create two functions to be able to reproduce what I mean:
First function:
function testPlot1()
pointData = rand(20000,3);
figure;
%hold on; % <- if commented out, does not work
plot3(pointData(:,1), pointData(:,2), pointData(:,3),'Marker', '.', 'MarkerEdgeColor', 'b','MarkerSize', 5, 'LineStyle', 'none');
axis equal;
xh = xlabel('X');
yh = ylabel('Y');
zh = zlabel('Z');
set([xh,yh, zh],...
'fontweight','bold',...
'fontsize',14,...
'color',[0,0,0]);
view(0,20);
end
Second function:
function testPlot2(fighandle)
axes(fighandle);
hold on;
plot3([0 3],[0 3],[0 3], 'r', 'LineWidth', 10);
end
If you now call
testPlot1();testPlot2(gca)
you will get the following:
If you however uncomment the "hold on" line in testPlot1() and call the above statement again, you will get:
To me this is unclear behavior. In the first case, testPlot1() creates a figure, draws the point cloud into it and modifies the axes properties. Then the call to testPlot2(gca) adds the line to the figure, but the line is clipped.
In the second case however the line is not clipped anymore. Why is it now not clipped and previously it was?
It seems to be related to the changes I make in the axes properties in testPlot1(). Could somebody explain this behavior to me? (why does it work with hold on, what do my changes in the axes properties cause)
hold on is a Matlab command (hold off turns it off again), where you can draw multiple elements on a single figure without the previous elements being erased.
What happens
If you call the plot function, a figure is created (or an already exisiting figure is used!) and Matlab draws a new plot into that figure. The previous plot that was in that figure is gone.
If you want to add more points to your plot, you can call hold on and then call plot again, this time with different numbers and maybe a different colour or so.
However, if you forget to turn hold off again for the active figure, any drawing activity you do (like plot) will be added to the figure. This is what happens in your second image in your question. You drew some points in the range 0 to 1, and then in the second function, you add some more but in the range 2 to 3. As a result, the axes expand to the range of 0 to 3.
Alternatively, you can call figure, which will cause a new figure to appear. figure_handle = figure(); will return a figure handle, which you can pass to your function, in case you have multiple figures and want to change one of them after a while.
Consider the following example code:
load sumsin;
s = sumsin+10; % example data series
time = linspace(0,5*24,1000);
figure(1);
subplot(311);
plot(time,s,'k');
subplot(312);
plot(time,s,'k');
hold on;
[s_denoised,~, ~] = wden(s,'minimaxi','s','sln',1,'db4');
plot(time,s_denoised,'r');
subplot(313);
plot(time,s,'k');
hold on;
plot(time,s_denoised,'r');
xlim([20 40]);
Resulting in
I would like to alter this plot by inserting lines between subplot 2 and 3 to show that subplot 3 is a portion of subplot2. For example:
How can this be achieved in matlab?
Edit:
I was thinking of something along the lines of generating a invisible axes over the entire figure, obtain the position of each subplot, the location of 20 and 40 will be a certain percentage of the subplot width so I could use the annotation command from here to start a line and then apply the same method to the third subplot to connect the lines with the desired location. I have trying this, but no solution so far.
Just for the sake of the answer, you could use annotation objects to get the effect that you're looking for, as correctly suggested in a comment. Note that their coordinates have to be normalized to the [0, 1] range with respect to the figure window, so it might be quite tedious to adjust them.
This does get the job done, but it's horrible. Don't do it this way.
Example
Since I don't have your original data, I'll draw something of my own (but similar to yours):
t = linspace(0, 120, 1000);
s_denoised = sin(t / 2);
s = s_denoised + 0.2 * randn(size(s_denoised));
subplot(3, 1, 1), plot(t, s, 'k')
subplot(3, 1, 2), plot(t, s, 'k', t, s_denoised, 'r')
subplot(3, 1, 3), plot(t, s, 'k', t, s_denoised, 'r'), xlim([20 40])
Now let's add "annotation" lines like you want:
annotation('doublearrow', [.26 .39], [.38 .38]); %// Top double-arrow line
annotation('doublearrow', [.13 .9], [.34 .34]); %// Bottom double-arrow line
annotation('line', [.325 .325], [.38 .37]); %// Top little connector
annotation('line', [.515 .515], [.35 .34]); %// Bottom little connector
annotation('line', [.325 .515], [.37 .35]); %// Line
Result:
A bit late in the game, but still it can be beneficial to know of these optional tools that are available at the file exchange (FEX):
inset2DAbsolute - creates an axes inset, defined using the larger axes, and corresponding annotations.
On-figure magnifier - is a zooming tool for 2D graphics of images on the same plot. It is composed of two blocks (the secondary axes and the magnifier). The secondary axes, which can be arbitrarily allocated within the limits of the figure, displays the area marked by the magnifier.
Interesting question.
However, from my experience, beautification of graphs and plots can be done more efficiently using graphics software.
I usually use excel + powerpoint for this purpose.
Therefore, my advice (which is not exactly a good answer for your question) is:
export your data to excel, using xlswrite
use excel to create the desired plots.
copy-paste the plots to power point for "hand-crafted" finishing...