How to draw differently spaced grid lines in Matlab - matlab

On mathworks, I have found a code which is suppossed to draw grid lines in a plot:
g_x = -25:1.25:0;
g_y = -35:2.5:-5;
for i = 1:length(g_x)
plot([g_x(i) g_x(i)],[g_y(1) g_y(end)],'k:')% y grid lines
hold on
end
for i=1:length(g_y)
plot([g_x(1) g_x(end)],[g_y(i) g_y(i)],'k:') % x grid lines
hold on
end
here's a link
I don't understand the plot command: e.g. the y grid lines - one of the inputs is a vector containing all the spacing points of the x-axis, where I want to have a grid. These points are given in two columns and they are assigned to the second vector, which only contains the first and the last point shown on the y-axis. As I understand this command, it will for example take the first element g_x(1) and g_y(1) and plot a : , it will then take g_x(2) and g_y(1) and plot :, and so on. But How does it keep on plotting : from g_y(1) continuously until g-y(end) ?

To directly answer your question, it simply plots the two endpoints of each grid line and since the default LineStyle used by plot is a solid line, they will automatically be connected. What that code is doing is creating all permutations of endpoints and plotting those to form the grid.
Rather than creating custom plot objects (if you're using R2015b or later), you can simply use the minor grid lines and modify the locations of the minor tick marks of the axes.
g_x = -25:1.25:0;
g_y = -35:2.5:-5;
ax = axes('xlim', [-25 0], 'ylim', [-35 -5]);
% Turn on the minor grid lines
grid(ax, 'minor')
% Modify the location of the x and y minor tick marks
ax.XAxis.MinorTickValues = g_x;
ax.YAxis.MinorTickValues = g_y;

Basically the code does this:
g_x = -25:1.25:0;
generates a array with values -25.0000 -23.7500 -22.5000 -21.2500 ... 0
These are the positions where vertical lines are drawn
The same holds for g_y, but of course this determines where horizontal lines are drawn.
The option 'k' determined that it is a dashed line.
And the loops just loo through the arrays.
So in the first iteration the plot function draws a line from the position
[-25, -35]
to the position
[-25, -5]
So if you want to change the grid, just change the values stored in g_x
g_x = -25:3.0:0;
would for example draw vertical lines with the width 3.0
I hope this makes sense for you.

Related

Creating a legend in MATLAB that includes scatter plots and normal plots

I want my legend to include the line from the plot and the marker from the scatterplot. For example,
rest = importdata('test.xlsx');
x = test.data(:,1);
y = test.data(:,2);
xx = min(x):0.001:max(x);
yy = interp1(x,y,xx,'cubic');
figure
s1 = scatter(x,y, 'filled', 'k');
hold on
p1 = plot(xx,yy, '--k');
legend(p1, 'x1');
This code creates the legend with only the dashes from the plot and not points from the scatterplot. I would like the legend to have the both the point and the dashed line at the same label. Something like "-.-"
Any help is much appreciated.
Thanks.
Option 1
Make a dummy plot with no data (nan) for the legend (also, as you can see here you can plot all the elements with one call to plot:
p = plot(nan,nan,'--ok', xx,yy,'--k', x,y,'ok');
set(p,{'MarkerFaceColor'},{'k'}); % fill the circles
legend('x1');
The result:
Option 2
Insted of legend(p1, 'x1');, write this:
[~,ico] = legend(p1,'x1'); % create the legend, and get handels to it's parts
ico(3).Marker = 'o'; % set the marker to circle
ico(3).MarkerFaceColor = 'k'; % set it's fill color to black
ico is:
3×1 graphics array:
Text (x1)
Line (x1)
Line (x1)
The first element is the text 'x1' in the figure. The second element is the dashed line, and the third is the (not-exist) marker of p1. This third element is reserved for cases like plot(xx,yy,'--ok'); where the legend include both marker and a line, but the line (in the legend) is represented with two points and the marker with only one, so we need different objects for them. Try to see what happens if you type ico(2).Marker = 'o'; in the example above.
Legend in MATLAB is additional axes that contains the same primitive object like lines and text.
If you want to draw custom legend the simple way will be using primitive commands line, text and patch for rectangles with filling. Also you can add one more axes object as a container.
By specifying p1 in the legend command you are telling MATLAB to only insert an item in the legend for the line corresponding to handle p1 - which is what you are seeing.
In your example case you just want
>>legend({'label_for_scatter','label_for_plot'});

Draw vertical line on histogram plot matlab

Matlab R2015b. I used the following code to draw the histogram:
close all;
hold on;
ko = histograms_windows_1_0{7};
histogram(ko);
set(gca,'XLim',[0 30],'XTick',0:5:30);
xticks = [0;0.16;0.33;0.5;0.66;0.83;1];
set(gca,'XTickLabel', xticks)
xlabel('Seconds');
ylabel('Correct Transitions');
That gives me the picture:
Now I want to add vertical line showing mean value by the "seconds" axis, I already know that value and also the standard deviation. Something similar to:
I have mn and stdv values. I've tried this:
mn = mean(ko) / 30;
stdv = std(ko) / 30;
hax=axes;
line([mn mn],get(hax,'YLim'))
hold off;
But it ignores previously drawn histogram and draws vertical line but only that line is shown, no histogram anymore. How that can be achieved?
The problem is the line
hax=axes;
This creates a new axis object which covers the previous one.
The solution is to change into
hax=gca;
so that the subsequent line goes to the same axis that contains the histogram.

How do I plot a horizontal line and a curve in the same graph in MATLAB?

I'm supposed to show the plot of data (curve) and a plot of the average of the data (flat horizontal line) in the same graph. My code computes everything fine and displays the curve in the graph, but I can't get the horizontal line to show up.
plot(1:24,hours3,'b-.',1:24, avg3,'r--');
So the plot of the column "hours3" shows up just fine, but the plot of the average "avg3" does not come up at all. It should be a flat line that extends from points 1 to 24 on the x-axis. Does anyone know why this is?
It's because plot(1:24,avg3,rx--) is interpreted as 24 single points. Using rx-- as linestyle shows you that the points are plotted right but not connected.
plot(1:24,hours3,'b-.',1:24, repmat(avg3,1,24),'r--');
Also with hold on you can keep plotting in an existing figure.
Try below code:
StartPoint=1;
EndPoint=24;
Resolution=1; % you can set 0.1 if you want more precision
Ave=Ave3;% set a value for Ave3
x=[StartPoint:Resolution:EndPoint];
NumberofPoints=((EndPoint-StartPoint)/Resolution)+1;
HrzLine=Ave*ones(1,NumberofPoints);
Curve=0.2*x.^3-4.*x.^2+8;
plot(x,HrzLine);
hold on;
plot(x,Curve);
The 2018b release has made adding horizontal lines (& vertical lines) much easier with yline() (xline() for verticle lines).
Xrng = 1:.01:24;
fh =#(x) 0.2*x.^3 - 4.*x.^2 + 50*sin(x)+ 8; % curve
plot(Xrng,fh(Xrng))
yline(0) % horizontal line at y = 0
Subsequent lines can be added just as easily.
yline(50) % horizontal line at y = 0
xline(12,'b--') % vertical line at x = 12 (blue, dashed)
Requires MATLAB R2018b or later.

Arc between two 3d vectors

How I can simply make an arc with a label in 3D Matlab plot? I have two 3D vectors (plot::Arrow3d)and I want to name an angle between them and I want to show it on 3D plot.
Edit1:
I use MuPad to render my drawing, I suppose to draw the arc between two vectors by plot::Arc3d(1, [0,0,0], n, al..bet). where n is simple to find. But I completely don't understand where the arc angle starts in 3D. Does somobody can show me how to find the zero angle.
Short answer, use the text function.
See if this gets you started:
%A couple of random points in 3 space
xyz1 = randn(3,1);
xyz2 = randn(3,1);
%Set up a figure, and create "arrow" plots within
figure(3781);
clf;
hold on
quiver3(0,0,0,xyz1(1), xyz1(2), xyz1(3),0,'b')
quiver3(0,0,0,xyz2(1), xyz2(2), xyz2(3),0,'r')
view(3)
%Add a line connecting teh arrows, and a text label
plot3([xyz1(1) xyz2(1)], [xyz1(2) xyz2(2)], [xyz1(3) xyz2(3)],'k:')
xyzCenter = mean([xyz1 xyz2],2);
h = text(xyzCenter(1), xyzCenter(2), xyzCenter(3), 'Label text here');
set(h,'Color','b')
get(h); %For more properties to set

MATLAB, Filling in the area between two sets of data, lines in one figure

I have a question about using the area function; or perhaps another function is in order...
I created this plot from a large text file:
The green and the blue represent two different files. What I want to do is fill in the area between the red line and each run, respectively. I can create an area plot with a similar idea, but when I plot them on the same figure, they do not overlap correctly. Essentially, 4 plots would be on one figure.
I hope this makes sense.
Building off of #gnovice's answer, you can actually create filled plots with shading only in the area between the two curves. Just use fill in conjunction with fliplr.
Example:
x=0:0.01:2*pi; %#initialize x array
y1=sin(x); %#create first curve
y2=sin(x)+.5; %#create second curve
X=[x,fliplr(x)]; %#create continuous x value array for plotting
Y=[y1,fliplr(y2)]; %#create y values for out and then back
fill(X,Y,'b'); %#plot filled area
By flipping the x array and concatenating it with the original, you're going out, down, back, and then up to close both arrays in a complete, many-many-many-sided polygon.
Personally, I find it both elegant and convenient to wrap the fill function.
To fill between two equally sized row vectors Y1 and Y2 that share the support X (and color C):
fill_between_lines = #(X,Y1,Y2,C) fill( [X fliplr(X)], [Y1 fliplr(Y2)], C );
You can accomplish this using the function FILL to create filled polygons under the sections of your plots. You will want to plot the lines and polygons in the order you want them to be stacked on the screen, starting with the bottom-most one. Here's an example with some sample data:
x = 1:100; %# X range
y1 = rand(1,100)+1.5; %# One set of data ranging from 1.5 to 2.5
y2 = rand(1,100)+0.5; %# Another set of data ranging from 0.5 to 1.5
baseLine = 0.2; %# Baseline value for filling under the curves
index = 30:70; %# Indices of points to fill under
plot(x,y1,'b'); %# Plot the first line
hold on; %# Add to the plot
h1 = fill(x(index([1 1:end end])),... %# Plot the first filled polygon
[baseLine y1(index) baseLine],...
'b','EdgeColor','none');
plot(x,y2,'g'); %# Plot the second line
h2 = fill(x(index([1 1:end end])),... %# Plot the second filled polygon
[baseLine y2(index) baseLine],...
'g','EdgeColor','none');
plot(x(index),baseLine.*ones(size(index)),'r'); %# Plot the red line
And here's the resulting figure:
You can also change the stacking order of the objects in the figure after you've plotted them by modifying the order of handles in the 'Children' property of the axes object. For example, this code reverses the stacking order, hiding the green polygon behind the blue polygon:
kids = get(gca,'Children'); %# Get the child object handles
set(gca,'Children',flipud(kids)); %# Set them to the reverse order
Finally, if you don't know exactly what order you want to stack your polygons ahead of time (i.e. either one could be the smaller polygon, which you probably want on top), then you could adjust the 'FaceAlpha' property so that one or both polygons will appear partially transparent and show the other beneath it. For example, the following will make the green polygon partially transparent:
set(h2,'FaceAlpha',0.5);
You want to look at the patch() function, and sneak in points for the start and end of the horizontal line:
x = 0:.1:2*pi;
y = sin(x)+rand(size(x))/2;
x2 = [0 x 2*pi];
y2 = [.1 y .1];
patch(x2, y2, [.8 .8 .1]);
If you only want the filled in area for a part of the data, you'll need to truncate the x and y vectors to only include the points you need.