Matlab: vertical lines at x-values specified by vector - matlab

I have a vector of x-values at which I would like to add vertical lines to a graph, say a row vector: vec = [1 2 3 4 5]
I know that you can add single vertical lines like this:
plot([1 1],[0 1])
(gives a vertical line at x=1 from y=0 to y=1).
But when I try something like
vec = [1 2 3 4 5];
lowLine = [0 0 0 0 0];
highLine = [1 1 1 1 1];
plot([vec vec],[lowLine highLine])
It does not give the required result, instead it gives a z-shape. Where am I going wrong?

In order to plot several lines in a single plot, you need to use the fact that MATLAB's plot function handles matrices as inputs, and that it sees each column of the inputs as different plots :
If X and Y are both matrices, then they must have equal size. The plot
function plots columns of Y versus columns of X.
Thus, in order to get the expected result, you need to write :
vec = [1 2 3 4 5];
lowLine = [0 0 0 0 0];
highLine = [1 1 1 1 1];
plot([vec;vec],[lowLine;highLine])
Result :

Related

Applying median filter to data with 2 axes

I have the following code:
x = VarName3;
y = VarName4;
x = (x/6000)/60;
plot(x, y)
Where VarName3 and VarName4 are 3000x1. I would like to apply a median filter to this in MATLAB. However, the problem I am having is that, if I use medfilt1, then I can only enter a single array of variables as the first argument. And for medfilt2, I can only enter a matrix as the first argument. But the data looks very obscured if I convert x and y into a matrix.
The x is time and y is a list of integers. I'd like to be able to filter out spikes and dips. How do I go about doing this? I was thinking of just eliminating the erroneous data points by direct manipulation of the data file. But then, I don't really get the effect of a median filter.
I found a solution using sort.
Median is the center element, so you can sort three elements, and take the middle element as median.
sort function also returns the index of the previous syntaxes.
I used the index information for restoring the matching value of X.
Here is my code sample:
%X - simulates time.
X = [1 2 3 4 5 6 7 8 9 10];
%Y - simulates data
Y = [0 1 2 0 100 1 1 1 2 3];
%Create three vectors:
Y0 = [0, Y(1:end-1)]; %Left elements [0 0 1 2 0 2 1 1 1 2]
Y1 = Y; %Center elements [0 1 2 0 2 1 1 1 2 3]
Y2 = [Y(2:end), 0]; %Right elements [1 2 0 2 1 1 1 2 3 0]
%Concatenate Y0, Y1 and Y2.
YYY = [Y0; Y1; Y2];
%Sort YYY:
%sortedYYY(2, :) equals medfilt1(Y)
%I(2, :) equals the index: value 1 for Y0, 2 for Y1 and 3 for Y2.
[sortedYYY, I] = sort(YYY);
%Median is the center of sorted 3 elements.
medY = sortedYYY(2, :);
%Corrected X index of medY
medX = X + I(2, :) - 2;
%Protect X from exceeding original boundries.
medX = min(max(medX, min(X)), max(X));
Result:
medX =
1 2 2 3 6 7 7 8 9 9
>> medY
medY =
0 1 1 2 1 1 1 1 2 2
Use a sliding window on the data vector centred at a given time. The value of your filtered output at that time is the median value of the data in the sliding window. The size of the sliding window is an odd value, not necessarily fixed to 3.

Plotting only parts of vector

I have a vector like this:
a = [1 2 0 0 3 4 0 5]
I wanna plot this vector but getting rid of the Os. So, I tried this:
> b = (a>0);
> c = a(b);
> plot(c);
The plot is just fine bit I'm not happy with the time axis. On the time axis, I have now consecutive steps; but I want it to be the corresponding time steps from a to the values i plot from c. So, in this case, my timeline should look like this:
> [1 2 5 6 8]
Any ideas?
Simply define a variable with your t and use the filter on it as well
a= [1 2 0 0 3 4 0 5]
t = 1:length(a)
idx=(a>0);
plot(t(idx), a(idx));
Set the undesired values of a to NaN, and plot ignores them and interjects the line where NaN occurs.
a(a==0)=NaN
find() does exactly what you want, return the index of every nonzero value.
a= [1 2 0 0 3 4 0 5];
b=find(a);
plot(b,a(b))
If you only want positive values, you also hook that into find:
b=find(a>0);

Matlab/Simulink: Convert Data Table (Measured) Into Lookup Table

I have simulated a magnetic system and I have 2 input variables and 1 output variable. The result looks like this:
myData = [...
0 0 1.1;...
0 1 1.2;...
0 2 1.2;...
1 0.1 2.1;...
1 0.9 2.2;...
1 2.05 2.2;...
3 0.1 3.1;...
3 1.2 3.2;...
3 1.9 3.2;...
];
Column 1 and 2 are the input values. Column 3 is the output variable:
x = myData(:,1);
y = myData(:,2);
z = myData(:,3);
I want to create a 2D lookup table in Simulink with x and y as inputs and z as an output. I do not get how to do this. It would be easy if the 2nd input variable would be evenly spaced like here:
x = [0 1 2];
y = [0 1 2];
z = [0 0 0; 1 2 3; 4 4 8]
In the Simulink lookup table block you would put:
In a nutshell:
How do I treat my data do be able to use a lookup table in Simulink?
The matlab/simulink command you are looking for is set_param.
The matlab command you are looking for in mat2str
You can set.
x = [0 1 2];
y = [0 1 2];
Then interpolate z corresponding to x and y, using the raw data available. This will form an evenly spaced LUT.

Boundaries and contours in Matlab

I have a binary image with non closed curves of 1-pixel width on it. I want to grab this curves as a list of points (in proper order). I found bwboundaries function which tries to wrap all non-zero pixels and thus in this case returns duplicate points:
>> A = [0 0 0; 1 1 1; 0 0 0];
>> b = bwboundaries(A)
ans =
[5x2 double]
>> b{1}
ans =
2 1
2 2
2 3
2 2
2 1
bwtraceboundary do the same
>> bwtraceboundary(A, [2 1], 'E')
ans =
2 1
2 2
2 3
2 2
2 1
Is there any standard method to get matrix like [2 1; 2 2; 2 3] immediately?
It produces double entries because your region is only one pixel wide. I don't think there's a standard method that handles your special problem directly. However, you can simply use the unique() function to eliminate double entries of the result.
To keep the original order of the points, just do:
b = bwboundaries(A);
[dummy, ind] = unique(b{1}, 'rows', 'first');
contour = b{1}(sort(ind), :);

Getting all pixel coordinates of a vector inside a image

I have an intensity/greyscale image, and I have chosen a pixel inside this image. I want to send vectors starting from this pixel in all directions/angles, and I want to sum all the intensities of the pixels touching one vector, for all vectors.
After this step I would like to plot a histogram with the intensities on one axis and the angle on the other axis. I think I can do this last step on my own, but I don't know how to create these vectors inside my greyscale image and how to get the coordinates of the pixels a vector touches.
I previously did this in C++, which required a lot of code. I am sure this can be done with less effort in MATLAB, but I am quite new to MATLAB, so any help would be appreciated, since I haven't found anything helpful in the documentation.
It might not be the best way to solve it, but you can do it using a bit of algebra, heres how...
We know the Point-Slope formula of a line passing through point (a,b) with angle theta is:
y = tan(theta) * (x-a) + b
Therefore a simple idea is to compute the intersection of this line with y=const for all const, and read the intensity values at the intersection. You would repeat this for all angles...
A sample code to illustrate the concept:
%% input
point = [128 128]; % pixel location
I = imread('cameraman.tif'); % sample grayscale image
%% calculations
[r c] = size(I);
angles = linspace(0, 2*pi, 4) + rand;
angles(end) = [];
clr = lines( length(angles) ); % get some colors
figure(1), imshow(I), hold on
figure(2), hold on
for i=1:length(angles)
% line equation
f = #(x) tan(angles(i))*(x-point(1)) + point(2);
% get intensities along line
x = 1:c;
y = round(f(x));
idx = ( y<1 | y>r ); % indices of outside intersections
vals = diag(I(x(~idx), y(~idx)));
figure(1), plot(x, y, 'Color', clr(i,:)) % plot line
figure(2), plot(vals, 'Color', clr(i,:)) % plot profile
end
hold off
This example will be similar to Amro's, but it is a slightly different implementation that should work for an arbitrary coordinate system assigned to the image...
Let's assume that you have matrices of regularly-spaced x and y coordinates that are the same size as your image, such that the coordinates of pixel (i,j) are given by (x(i,j),y(i,j)). As an example, I'll create a sample 5-by-5 set of integer coordinates using MESHGRID:
>> [xGrid,yGrid] = meshgrid(1:5)
xGrid =
1 2 3 4 5
1 2 3 4 5
1 2 3 4 5
1 2 3 4 5
1 2 3 4 5
yGrid =
1 1 1 1 1
2 2 2 2 2
3 3 3 3 3
4 4 4 4 4
5 5 5 5 5
Next we can define a line y = m*(x - a) + b passing through the coordinate system by selecting some values for the constants and computing y using the x coordinates of the grid:
>> a = 0;
>> b = 1;
>> m = rand
m =
0.5469
>> y = m.*(xGrid(1,:)-a)+b
y =
1.5469 2.0938 2.6406 3.1875 3.7344
Finally, we find the y points in the grid that differ from the points computed above by less than the grid size:
>> index = abs(yGrid-repmat(y,size(yGrid,1),1)) <= yGrid(2,1)-yGrid(1,1)
index =
1 0 0 0 0
1 1 1 0 0
0 1 1 1 1
0 0 0 1 1
0 0 0 0 0
and use this index matrix to get the x and y coordinates for the pixels crossed by the line:
>> xCrossed = xGrid(index);
>> yCrossed = yGrid(index);