Connecting subplots with lines in matlab - matlab

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...

Related

Displaying more than 50 legend entries

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!

How to get variable scales on y axis for same graph in matlab plotting?

I am working on matlab programming, my problem is that in the same graph on y axis i need to have variable scaling, for example from 0.1 to 1 i need to have a gap between scales 0.1, but after 1 I need to have scale gap of 2, is there some command available for the same?
There is an example by The Mathworks on Matlab answers which does pretty much what you want to achieve. The idea is to create 2 axes on the same figure and use one axes to plot some data (eg. for the 0.1:0.1:1 tick marks) and the rest on the other axes. Then you overlay both axes with a transparent background:
%Create two overlapping axes
axes_handle_1 = axes;
axes_position = get(axes_handle_1, 'Position');
axes_handle_2 = axes('Position', axes_position);
%Create some data with a large gap in the x domain
my_x_data = [1:10 25:35];
my_y_data = rand(1, length(my_x_data));
%Plot the two sections of data on different axes objects
plot(axes_handle_1, my_x_data(1:10), my_y_data(1:10))
plot(axes_handle_2, my_x_data(11:end), my_y_data(11:end))
%Link the y axis limits and fontsize property of the axes objects
linkaxes([axes_handle_1 axes_handle_2], 'y');
linkprop([axes_handle_1 axes_handle_2], 'FontSize');
%Set the x range limits and tick mark positions of the first axes object
set(axes_handle_1, 'XLim', [1 21], ...
'XTick', [1 5 10])
%Set the x range limits and tick mark positions for the second axes object.
%Also set the background color to 'none', which makes the background
%transparent.
set(axes_handle_2, 'Color', 'none', ...
'YTickLabel', [], ...
'XLim', [14 35], ...
'XTick', [25 30 35])
It's quite straightforward and to my knowledge there is no built-in way to do it otherwise, except maybe with submissions from the File Exchange. Anyhow if you have questions about the above code please ask!
Please use gca property of matlab. In gca you can set a variable as your scales. Make that variable by merging two different scales
x=[1:80];
y=[.1:.1:8];
figure
plot(x,y);
%First Scale
scale1=[.1:.1:1];
%New scale is being started from 3. If we start from 1, 1 will be repeated
scale2=[3:2:9];
%Merging two variables scale1 and scale2
set(gca,'YTick',[scale1 scale2]);
Please refer http://www.mathworks.in/help/matlab/creating_plots/change-tick-marks-and-tick-labels-of-graph.html
You can also try the idea of scaling one dataset so that it has a similar magnitude as the other data set. Here you can multiply one dataset by 100 (or any suitable scaling parameter), and then it will be similar in size to the other data set. In order to clearly mention which data has been scaled in the graph use the legend.
plot(x,data1,x,100*data2)
legend('data1','100*data2','location','southeast')
Hope this helps.

Plot data behind 2D plot in Matlab

I have a fairly complex plotting problem that i thought it would be interesting to get a solution to. Say i have two plots, number 1:
This plot was created using plotyy.
And number 2:
This plot was created using plot3(x, y, z, '.')
Now, the complex part is i want to take plot number 2, watermark it and put it behind plot number 1. Which would result in something like this:
Effectively what i want to show is that plot 1 is made from data that looks like plot 2. Now i haven't been able to find how to do this so it may not even be possible, but if it can be done then it would be a great tutorial to have on stack overflow!
You can do this but it will take some work to get the axes formatted so they look nice.
What you need to do is put one axes object on top of another axes; however, to prevent the top axes from occluding the bottom one you need to set the 'Color' property of the top axes object to 'none'.
Here is an example script that generates something similar to what you are looking for
f = figure;
axes();
x = rand(100,3)*3 + 3;
plot3(x(:,1), x(:,2), x(:,3),'.');
axes('Color', 'none');
x = -5:5;
y = x.^2;
line(x,y, 'Color', 'r', 'LineWidth', 2);
Here is the resulting figure:
If you don't like how this works out you can try to project your 3D data into 2D and then draw that projection as an image behind your lines. Here is a link to a discussion about how you might go about creating the 2D projection.

MATLAB: line specification marker size

When plotting multiple data series using both line specification (X,Y,linespec) triplets and (PropertyName,PropertyValue) doublets, only a single MarkerSize can be specified and this size applies to all data series. For instance,
plot(X1,Y1,'.b',X2,Y2,'-r','MarkerSize',5)
Is it possible to specify a different MarkerSize for each of the different data series without resorting to plotting the data series separately or subsequently altering plot handle properties? Neither of the following two commands is valid, but they give an idea of the desired result:
plot(X1,Y1,'.b',X2,Y2,'-r','MarkerSize',[5 10])
plot(X1,Y1,'.b','MarkerSize',5,X2,Y2,'-r','MarkerSize',10)
Try:
h = plot(X1,Y1,'.b',X2,Y2,'*r');
set(h(1),'MarkerSize',5);
set(h(2),'MarkerSize',2);
You can use scatter. It has the SizeData property which is a vector.
x = rand(10,1);
y = rand(10,1);
s = scatter(x,y);
set(s,'SizeData',linspace(1,100,10))
If you want to use line plot with markers, you can draw your plot, use hold on, and then draw scatter on top of it.
For that it is probably
plot(x1,0,'+','MarkerSize',10)
Or any other plot within the loop just
plot(x?, 0, '+', 'MarkerSize', 10, 'MarkerEdgeColor', 'r')

How do I visualize a matrix with colors and values displayed?

I want to create images like this from a double precision matrix using MATLAB.
Sample image:
http://twitpic.com/2xs943
You can create this sort of plot yourself pretty easily using the built-in functions imagesc and text and adjusting a number of parameters for the graphics objects. Here's an example:
mat = rand(5); % A 5-by-5 matrix of random values from 0 to 1
imagesc(mat); % Create a colored plot of the matrix values
colormap(flipud(gray)); % Change the colormap to gray (so higher values are
% black and lower values are white)
textStrings = num2str(mat(:), '%0.2f'); % Create strings from the matrix values
textStrings = strtrim(cellstr(textStrings)); % Remove any space padding
[x, y] = meshgrid(1:5); % Create x and y coordinates for the strings
hStrings = text(x(:), y(:), textStrings(:), ... % Plot the strings
'HorizontalAlignment', 'center');
midValue = mean(get(gca, 'CLim')); % Get the middle value of the color range
textColors = repmat(mat(:) > midValue, 1, 3); % Choose white or black for the
% text color of the strings so
% they can be easily seen over
% the background color
set(hStrings, {'Color'}, num2cell(textColors, 2)); % Change the text colors
set(gca, 'XTick', 1:5, ... % Change the axes tick marks
'XTickLabel', {'A', 'B', 'C', 'D', 'E'}, ... % and tick labels
'YTick', 1:5, ...
'YTickLabel', {'A', 'B', 'C', 'D', 'E'}, ...
'TickLength', [0 0]);
And here's the figure this generates:
If you run into trouble with the x-axis tick labels you choose being too wide and overlapping one another, here's how you can handle it:
Newer versions of MATLAB: Not sure which version this was added, but in newer versions axes objects now have the properties '{X|Y|Z}TickLabelRotation', which allow you to rotate the labels and fit them better.
Older versions of MATLAB: For older versions you can find some submissions on the MathWorks File Exchange that can rotate the tick label text, like XTICKLABEL_ROTATE from Brian Katz.
h = imagesc(magic(8))
impixelregion(h)
http://www.mathworks.com/help/toolbox/images/ref/impixelregion.html
Requires Image Processing Toolbox
If you only care about looking at zero/non-zero entries in your matrix (e.g. if it's sparse), use spy.
Else, use imagesc.
PS: I can't access your image
I expect you could persuade Matlab to draw that, if you look at the File Exchange you may find someone has already written the code. But it would be a lot easier, if you don't have the code, to use MS Excel.
EDIT: So I gave this some more thought and here's what I came up with. I've not mastered posting graphics to SO, so trust me, this will lead you towards a solution. But it would honestly be easier with Excel.
First define a matrix with your data values; I call the matrix G in the following. Then execute the commands:
image(G);
colormap(gray)
Now, I had to do some fiddling around, rescaling the data, to get a good graphic, but this should produce a gray-scale plot with numeric axes. Now, go to your figure window and open the plot tools.
Select the X axis and hit the Ticks button. All you have to do now is edit the labels to the texts that you want. Do the same for the Y axis. Write the numbers in the squares on the plot -- use the Text Box from the Annotations menu.
After a lot of fiddling about you'll have the graphic you want. At this point, I suggest that you choose the menu command File | Generate M-File and do just that. If you want to create such graphics programmatically in future just turn the generated M file into a proper function that does what you want.
But it's still a lot easier in Excel.