How can I specify different points in the plot in matlab - matlab

I have generated a data set in matlab then some outliers embedding in the data. I would like to plot it and since I'm new in matlab I don't know how to specify the outliers from inliers by different sign or different color. The points which are outlyingness with respect to the x axis, y axis and both of them. This is the matlab codes for that;
pd = makedist('Normal');
rng(38)
a = random(pd,100,1);
b = datasample(1:100,40,'Replace',false);
pd1 = makedist('Normal','mu',10*sqrt(2),'sigma',0.1);
a(b)=random(pd1,40,1);
a=reshape(a,[50,2]);
plot(a(:,1),a(:,2),'O')
I would be appreciated if you could help me.

In this example I assumed that the points which distance along OX axis is greater than 3 are outliers and marked them red (whereas normal points are marked blue):
centroid = mean(a);
distx = a(:,1) - centroid(1);
disty = a(:,2) - centroid(2);
outliers_x = distx > 3;
plot(centroid(1), centroid(2), 'xk')
hold on
plot(a(outliers_x,1),a(outliers_x,2),'or')
plot(a(~outliers_x,1),a(~outliers_x,2),'ob')
hold off
Note that I've also displayed the centroid as a black "X" mark.
hold on/hold off are used to "stack" several plots (or images) together
You may want to read hold() reference. Also here you'll find which markers and colors are available.

To answer to my question I have written the following codes, in order to specify 4 groups of observations with different color.
pd = makedist('Normal');
rng(38)
a = random(pd,100,1);
b = datasample(1:100,40,'Replace',false);
pd1 = makedist('Normal','mu',10*sqrt(2),'sigma',0.1);
a(b)=random(pd1,40,1);
a=reshape(a,[50,2]);
hold all;
aa=(a >= 10 | a >= 10);
rep=repmat(0, 1, 50);
aaa=[rep',aa];
n=50;
for i=1:n; plot(a(i,1),a(i,2),'o','col',aaa(i,:));
end

Related

Finding where two histograms cross paths - MATLAB

I am generating two histograms using the histogram function from Matlab that are both normalized using the probability argument.
However, once I generate two histograms as shown below, I'd like to be able to find the exact point at which the histograms would cross paths, assuming the histograms were drawn using lines instead of bars. Unfortunately, this form of histogram doesn't allow for lines, it just has bars. There is a hist function which can be manipulated in Matlab to draw a histogram as lines instead of bars, however, it doesn't easily normalize.
Hence, ideally, I'd like to use histogram() to plot the 2 histograms and find where they cross. See image below:
Here's an example of how the graphs can be created:
x = randn(2000,1);
y = 1 + randn(5000,1);
h1 = histogram(x);
hold on
h2 = histogram(y);
h1.Normalization = 'probability';
h1.BinWidth = 0.25;
h2.Normalization = 'probability';
h2.BinWidth = 0.25;
Now from here, I want to find the point where the two histograms cross paths. Note, the intersection value is the intersection (in the mathematical sense). This is not what I'm looking for. I'm looking for the x coordinate of where the two histograms cross at their outer boundaries. For example, in the attached image, the answer would be ~2.5.
From your example data, with a simple modification:
x = randn(2000,1);
y = 1 + randn(5000,1);
h1 = histogram(x);
hold on
h2 = histogram(y);
h1.Normalization = 'probability';
h1.BinWidth = 0.25;
h1.BinLimits=[min([x(:); y(:)]) max([x(:); y(:)])];
h2.Normalization = 'probability';
h2.BinWidth = 0.25;
h2.BinLimits=[min([x(:); y(:)]) max([x(:); y(:)])];
data1=h1.Values;
data2=h2.Values;
intersection_value=find(data2>data1,1); % this is the index, bad variable name

How to plot a Diagonal Histogram in Matlab

Given scatter data, or a matrix, I would like to generate a nice plot such as the one shown below, with all 3 histograms and a colored matrix. I'm specifically interested in the diagonal histogram, which ideally, would correspond to the diagonals of a matrix:
Source figure: www.med.upenn.edu/mulab/jpst.html
The existing command scatterhist is not that powerful to generate this type of graph. Any ideas?
Thanks!
EDIT:
Following #Cris Luengo's hints, I came up with the following code which does some first work at the inclined histogram: WORK IN PROGRESS (HELP WELCOME)!!
b = [0 1 2 3 4 5 6 7 8 9 10];
h = [0.33477 0.40166 0.20134 0.053451 0.008112 0.000643 2.7e-05 0 0 0 0];
wid = 0.25; bb = sort([b-wid b-wid b+wid b+wid]);
kk = [zeros(numel(h),1) h(:) h(:) zeros(numel(h),1)];
kk = reshape(kk',[1,numel(kk)]);
pp=patch(bb,kk,'b');axis([-.5 5 0 .5])
set(gca,'CameraUpVector',[-1,.08,0]);axis square
EDIT 2: Using rotation
phi = pi/4;
R = [cos(phi),-sin(phi);sin(phi),cos(phi)];
rr = [bb' kk'] * R;
bb = rr(:,1); kk = rr(:,2);
patch(bb,kk,'b'); axis([-.5 3 -4 .5])
Here is a recipe to plot the diagonal histogram, if you can do that I’m sure you can figure out the rest too.
Compute the histogram, the bin counts are h, the bin centers are b.
Build a coordinate matrix, attaching the coordinates of a point on the x-axis at the left and right ends of the histogram:
coords = [b(:),h(:)];
coords = [coord;b(end),0;b(1),0];
Using patch you can now plot the histogram as follows:
patch(coords(1,:),coords(2,:));
To plot a rotated histogram you can simply multiply the coords matrix with a rotation matrix, before using patch:
phi = pi/4;
R = [cos(phi),-sin(phi);sin(phi),cos(phi)];
coords = R * coords;
You might need to shift the plot to place it at the right location w.r.t. the other elements.
I recommend that you place all these graphic elements in the same axes object; you can set the axes’ visibility to 'off' so that it works only as a canvas for the other elements.
It will be a bit of work to get everything placed as in the plot you show, but none of it is difficult. Use the low-level image, line,patch and text to place those types of elements, don’t try to use the higher-level plotting functions such as plot, they don’t provide any benefits over the low-level ones in this case.

Find the real time co-ordinates of the four points marked in red in the image

To be exact I need the four end points of the road in the image below.
I used find[x y]. It does not provide satisfying result in real time.
I'm assuming the images are already annotated. In this case we just find the marked points and extract coordinates (if you need to find the red points dynamically through code, this won't work at all)
The first thing you have to do is find a good feature to use for segmentation. See my SO answer here what-should-i-use-hsv-hsb-or-rgb-and-why for code and details. That produces the following image:
we can see that saturation (and a few others) are good candidate colors spaces. So now you must transfer your image to the new color space and do thresholding to find your points.
Points are obtained using matlab's region properties looking specifically for the centroid. At that point you are done.
Here is complete code and results
im = imread('http://i.stack.imgur.com/eajRb.jpg');
HUE = 1;
SATURATION = 2;
BRIGHTNESS = 3;
%see https://stackoverflow.com/questions/30022377/what-should-i-use-hsv-hsb-or-rgb-and-why/30036455#30036455
ViewColoredSpaces(im)
%convert image to hsv
him = rgb2hsv(im);
%threshold, all rows, all columns,
my_threshold = 0.8; %determined empirically
thresh_sat = him(:,:,SATURATION) > my_threshold;
%remove small blobs using a 3 pixel disk
se = strel('disk',3');
cleaned_sat = imopen(thresh_sat, se);% imopen = imdilate(imerode(im,se),se)
%find the centroids of the remaining blobs
s = regionprops(cleaned_sat, 'centroid');
centroids = cat(1, s.Centroid);
%plot the results
figure();
subplot(2,2,1) ;imshow(thresh_sat) ;title('Thresholded saturation channel')
subplot(2,2,2) ;imshow(cleaned_sat);title('After morpphological opening')
subplot(2,2,3:4);imshow(im) ;title('Annotated img')
hold on
for (curr_centroid = 1:1:size(centroids,1))
%prints coordinate
x = round(centroids(curr_centroid,1));
y = round(centroids(curr_centroid,2));
text(x,y,sprintf('[%d,%d]',x,y),'Color','y');
end
%plots centroids
scatter(centroids(:,1),centroids(:,2),[],'y')
hold off
%prints out centroids
centroids
centroids =
7.4593 143.0000
383.0000 87.9911
435.3106 355.9255
494.6491 91.1491
Some sample code would make it much easier to tailor a specific solution to your problem.
One solution to this general problem is using impoint.
Something like
h = figure();
ax = gca;
% ... drawing your image
points = {};
points = [points; impoint(ax,initialX,initialY)];
% ... generate more points
indx = 1 % or whatever point you care about
[currentX,currentY] = getPosition(points{indx});
should do the trick.
Edit: First argument of impoint is an axis object, not a figure object.

Finding 2D area defined by contour lines in Matlab

I am having difficulty with calculating 2D area of contours produced from a Kernel Density Estimation (KDE) in Matlab. I have three variables:
X and Y = meshgrid which variable 'density' is computed over (256x256)
density = density computed from the KDE (256x256)
I run the code
contour(X,Y,density,10)
This produces the plot that is attached. For each of the 10 contour levels I would like to calculate the area. I have done this in some other platforms such as R but am having trouble figuring out the correct method / syntax in Matlab.
C = contourc(density)
I believe the above line would store all of the values of the contours allowing me to calculate the areas but I do not fully understand how these values are stored nor how to get them properly.
This little script will help you. Its general for contour. Probably working for contour3 and contourf as well, with adjustments of course.
[X,Y,Z] = peaks; %example data
% specify certain levels
clevels = [1 2 3];
C = contour(X,Y,Z,clevels);
xdata = C(1,:); %not really useful, in most cases delimters are not clear
ydata = C(2,:); %therefore further steps to determine the actual curves:
%find curves
n(1) = 1; %n: indices where the certain curves start
d(1) = ydata(1); %d: distance to the next index
ii = 1;
while true
n(ii+1) = n(ii)+d(ii)+1; %calculate index of next startpoint
if n(ii+1) > numel(xdata) %breaking condition
n(end) = []; %delete breaking point
break
end
d(ii+1) = ydata(n(ii+1)); %get next distance
ii = ii+1;
end
%which contourlevel to calculate?
value = 2; %must be member of clevels
sel = find(ismember(xdata(n),value));
idx = n(sel); %indices belonging to choice
L = ydata( n(sel) ); %length of curve array
% calculate area and plot all contours of the same level
for ii = 1:numel(idx)
x{ii} = xdata(idx(ii)+1:idx(ii)+L(ii));
y{ii} = ydata(idx(ii)+1:idx(ii)+L(ii));
figure(ii)
patch(x{ii},y{ii},'red'); %just for displaying purposes
%partial areas of all contours of the same plot
areas(ii) = polyarea(x{ii},y{ii});
end
% calculate total area of all contours of same level
totalarea = sum(areas)
Example: peaks (by Matlab)
Level value=2 are the green contours, the first loop gets all contour lines and the second loop calculates the area of all green polygons. Finally sum it up.
If you want to get all total areas of all levels I'd rather write some little functions, than using another loop. You could also consider, to plot just the level you want for each calculation. This way the contourmatrix would be much easier and you could simplify the process. If you don't have multiple shapes, I'd just specify the level with a scalar and use contour to get C for only this level, delete the first value of xdata and ydata and directly calculate the area with polyarea
Here is a similar question I posted regarding the usage of Matlab contour(...) function.
The main ideas is to properly manipulate the return variable. In your example
c = contour(X,Y,density,10)
the variable c can be returned and used for any calculation over the isolines, including area.

Create a tailored colorbar in matlab

I have to create a map to show how far o how close some values are from a range and give them colors in consequence. Meanwhile, values that are within that range should have another different color.
For example: only the results that are within [-2 2] can be considered valid. For the other values, colors must show how far are from these limits (-3 lighter than -5, darker)
I've tried with colorbar but I'm not able to set up a self-defined color scale.
Any idea??
Thanks in advance!
You need to define a colormap for the range of values you have.
The colormap is N*3 matrix, defining the RGB values of each color.
See the example below, for a range -10:10 and valid values v1,v2:
v1=-3;
v2=+3;
a = -10:10;
graylevels=[...
linspace(0,1,abs(-10-v1)+1) , ...
ones(1, v2-v1-1) , ...
linspace(1,0,abs(10-v2)+1)];
c=repmat(graylevels , [3 1])';
figure;
imagesc(a);
colormap(c);
Here is some code that I just put together to demonstrate a simple means of creating your own lookup table and assigning values from it to the image that you're working with. I'm assuming that your results are in a 2D array and I just used randomly assigned values, but the concept is the same.
I mention the potentila use of HSV as a coloring scheme. Just note that, that requires you to have a m by n by 3 matrix. The top layer is the H - hue, 2nd being the S - saturation and the 3rd being the V or value (light/dark). Simply set the H and S to whatever values you want for the color and vary the V in a similar manner as shown below and you can get the varied light and dark color you want.
% This is just assuming a -10:10 range and randomly generating the values.
randmat = randi(20, 100);
randmat = randmat - 10;
% This should just be a black and white image. Black is negative and white is positive.
figure, imshow(randmat)
% Create your lookup table. This will illustrate having a non-uniform
% acceptable range, for funsies.
vMin = -3;
vMax = 2;
% I'm adding 10 here to account for the negative values since matlab
% doesn't like the negative indicies...
map = zeros(1,20); % initialized
map(vMin+10:vMax+10) = 1; % This will give the light color you want.
%linspace just simply returns a linearly spaced vector between the values
%you give it. The third term is just telling it how many values to return.
map(1:vMin+10) = linspace(0,1,length(map(1:vMin+10)));
map(vMax+10:end) = linspace(1,0,length(map(vMax+10:end)));
% The idea here is to incriment through each position in your results and
% assign the appropriate colorvalue from the map for visualization. You
% can certainly save it to a new matrix if you want to preserve the
% results!
for X = 1:size(randmat,1)
for Y = 1:size(randmat,2)
randmat(X,Y) = map(randmat(X,Y)+10);
end
end
figure, imshow(randmat)