Fit a distribution line in a histogram on Matlab - matlab

This is my code and the result I got. Something is not right — I used histfit(cntH,NumBins,'kernel'), and I was expecting the distribution line to start from zero and fit into the bars
How can I fix that?
clear all
clc
% yG = total
load yH
% specify number of bins and edges of those bins; this example evenly spaces bins
NumBins = 100;
BinEdges = linspace(0,35,70);
% use histcounts and specify your bins
cntH = histcounts(yH,'BinEdges',BinEdges);
% plot
figure(1); cla; hold on;
% convert bin edges into bin centers
b = BinEdges(1:end-1)+diff(BinEdges)/2
% use bar
bar(b,[cntH'],'stacked')
histfit(cntH,NumBins,'kernel');
% Labels
xlabel('Length (mm)')
ylabel('Count (log scale)')
set(gca,'YScale','log')
title('Count (log scale)')

Related

Generate a mesh with unequal steps based on a density function, using Matlab

I'm trying to generate a 1D mesh with unequal step length, and with a fixed number of elements [same as the initial mesh].
The length should be proportional to a node density. In the example, this density is inversely proportional to the gradient of a function.
[imagine for example that you have a distribution of the temperature in a 1D mesh, and you want to make the mesh denser in the parts of the mesh where the temperature gradient is higher]
This is what I coded so far:
% % % Initial fixed-step 1D mesh
X=(0:.01:2)';
% % % Values of a function at each mesh node [in this example, f(x)=5*sin(2*pi*x)*x ]
Y=5*sin(2*pi*X).*X;
% % % Calculate density of mesh points based on the Y function gradient
rho=[1e-9; abs(diff(Y))];
% % % Calculate x-steps from the original mesh
h = diff(X);
% % % Rescale the steps based on the inverse of the density
F = cumsum([0; h]./rho);
% % % Make sure F is between 0 and 1
F = F/F(end);
% % % Calculate the new mesh with scaled steps
X2 = X(1) + F * (X(end)-X(1));
% % % Interpolate the function Y at the new positions
Y2 = interp1(X,Y,X2);
% % % Plot
figure
subplot(2,1,1)
hold on
plot(X,Y,'ko-')
plot(X2,Y2,'r.-')
xlabel('x')
ylabel('y')
subplot(2,1,2)
plot(X,rho,'ko-')
xlabel('x')
ylabel('rho')
There are a few problems with this approach:
1. as you see from this example, there are big jumps when the density is very low (gradient almost zero). How could I implement a minimum/maximum time step size?
2. the node density is calculated correctly, but after "integrating" the unequal steps it can happen that the imposed large time step when the gradient is small causes to skip a high-gradient region that should have finer time-steps. [for example, please take a look at the region 1.8-1.9 in the example below, which should have small time step because it has high node density, but the large step size at ~1.75 causes to skip a large section of X]
Any suggestion to improve my code will be appreciated!
Calculate the cumulative sum (CDF) of rho. Take equally spaced samples from the CDF. Map from CDF to X to get new X3. Map from X3 to Y to get Y3:
CDF = cumsum(rho);
eq_smpl = linspace(CDF(1), CDF(end), numel(CDF)+1).';
eq_smpl = eq_smpl(1:end-1) + diff(eq_smpl)/2; %use center points
X3 = interp1(CDF, X, eq_smpl);
Y3 = interp1(X, Y, X3);
plot(X3,Y3,'ro-')
hold on
plot(X,Y,'k.')
The third subplot shows the the result.
rahnema1's answer gave me a huge help, but there were still two remaining issues:
1- the first element of the new mesh is not identical to the first element of the original mesh
2- in case the gradient is zero at some point, the interp1 function will give error ["The grid vectors are not strictly monotonic increasing."]
For the 1st point, I replaced the two lines defining eq_smpl with the following line:
eq_smpl = linspace(CDF(1), CDF(end), numel(CDF))';
[taking as many elements as CDF, and not centering the points]
For the 2nd point, I added a line after the calculation of rho to replace eventual 0 with small non-zero values:
rho(rho==0)=1e-12;
The final code that does what I want is the following:
% % % Initial fixed-step 1D mesh
X=(0:.01:2)';
% % % Values of a function at each mesh node [in this example, f(x)=5*sin(2*pi*x)*x ]
Y=5*sin(2*pi*X).*X;
% % % Calculate density of mesh points based on the Y function gradient
rho=[0; abs(diff(Y)./abs(diff(X)))];
% % % Replace eventual 0 with small non-zero values
rho(rho==0)=1e-12;
CDF = cumsum(rho);
eq_smpl = linspace(CDF(1), CDF(end), numel(CDF))';
% % % Calculate new mesh
X3 = interp1(CDF, X, eq_smpl);
% % % Interpolate the function Y at the new positions
Y3 = interp1(X, Y, X3);
% % % Plot
figure
subplot(2,1,1)
hold on
plot(X,Y,'ko-')
plot(X3,Y3,'r.-')
xlabel('x')
ylabel('y')
subplot(2,1,2)
plot(X,rho,'ko-')
xlabel('x')
ylabel('rho')
Thank you again to rahnema1 for providing 90% of the answer [probably I didn't explain very well the original request]!

Using roof of a graph as x-axis for another

I've plotted a graph using pcolor which gives me the following graph-
My aim is to use the roof of the graph (by roof) I mean the highest axis (in this case, the line which is defined by y=57) as the base for a further graph.
I was able to use hold on to generate the following-
Code for this (removed some parts that defined the axis labels etc for brevity)-
load sparsemap ;
load d ;
residues = 57 ;
z = zeros(residues,residues); % define the matrix
index = find(sparsemap(:,3) ~= 0) ;
values = length(index);
hold on
%Plots the map you see in the first photo-
for k = 1:values
z(sparsemap(index(k),1),sparsemap(index(k),2)) = sparsemap(index(k),3);
z(sparsemap(index(k),2),sparsemap(index(k),1)) = sparsemap(index(k),3);
end
%Plots the line plot at the bottom of the graph.
A = d(:,1);
B = d(:,2) ;
plot(A, B) ;
pcolor(1:residues,1:residues,z);
works = load('colormap_works');
colormap(works);
colorbar;
As you can see, the line plot is using the same x axis as the first graph.
I am trying to get the line plot to come on top of the figure. I imagine a final figure like so-
Any ideas as to how I can use the top part of the first graph?
You can use 2 subplots. Here is an example:
data = randi(50,20,20); % some data for the pcolor
y = mean(data); % some data for the top plot
subplot(5,1,2:5) % create a subplot on the lower 4/5 part for the figure
pcolor(data) % plot the data
colormap hot;
h = colorbar('east'); % place the colorbar on the right
h.Position(1) = 0.94; % 'push' the colorbar a little more to the right
ax = gca;
pax = ax.Position; % get the position for further thightning of the axes
ax.YTick(end) = []; % delete the highest y-axis tick so it won't interfere
% with the first tick of the top plot
subplot(5,1,1) % create a subplot on the upper 1/5 part for the figure
plot(1:20,y) % plot the top data
ylim([0 max(y)]) % compact the y-axis a little
ax = gca;
ax.XAxis.Visible = 'off'; % delete the x-axis from the top plot
ax.Position(2) = pax(2)+pax(4); % remove the space between the subplots
Which creates this:

Fitting Probability distribution function in eac histogram for each bin data using matlab.....?

I have x data and I did binning and created histogram of each bin.Now I want to fit the probability distribution function in each bin so I can see histogram and probability distribution function at the same graph. Here 'X' is in horizontal axis data and 'Y' represent vertical axis data of the same datasets. I have written the code below
X = load data1 ; Y = load data2
topEdge = 10; % upper limit
botEdge = 0;
numBins = 20;
binEdges = linspace(botEdge, topEdge, numBins+1);
[h,whichBin] = histc(X, binEdges)
% Histrogram plot of each bin
for i = 1:numBins
flagBinMembers = (whichBin == i); %Creates vector of the indices of the data entries that are in bin i
BinMean(i) = mean(power_ref(flagBinMembers)); %Calculate mean value in this bin
BinStd(i) = std(power_ref(flagBinMembers));
x = power_ref(flagBinMembers) - BinMean(i);
mu = power_ref(flagBinMembers)- BinMean(i); sigma =power_ref(flagBinMembers)- BinStd(i);
figure();
histogram(x, 'Normalization', 'pdf')
hold on;
Y = normpdf(x,mu,sigma);
plot(x,Y);
hold off
end
After running this code I am not getting the fitted 'pdf' and histogram on same curve. I correctly got histogram but not 'pdf'. Can any one suggest me or help me ....?? Thank you for your such patient for reading this !
I am getting such curve output : output of first bin Output of 2nd bin
As you can see histogram and pdf not fitting. Where I am making mistake...??

Convert Matlab code into Simulink

I would like to convert a image processing program(part of the program below) from Matlab to Simulink and possibly convert the simulink diagram into C code later on. I have 0 experience in Simulink and was wondering if there's any limitations on the types of matlab program/functions that can be converted and how I would go about doing this. Thanks.
clear all
clc
% Read in an image 1
C1 = imread('cloud1.jpg');
Cloud1 = C1(:,:,1); % use only one color
%Cloud1 = Cloud1'; % transpose to get (x,y) instead of (y,x)
Cloud1_xsize = size(Cloud1,2); % get x size of image
Cloud1_ysize = size(Cloud1,1); % get y size of image
%figure(3), imshow(Cloud1) % to plot you need to transpose back to their coordinate system
%hold on
% Read in an image 2
C2 = imread('cloud2.jpg');
Cloud2 = C2(:,:,1); % use only one color
%Cloud2 = Cloud2'; % transpose to get (x,y) instead of (y,x)
Cloud2_xsize = size(Cloud2,2); % get x size of image
Cloud2_ysize = size(Cloud2,1); % get y size of image
%figure(2), imshow(Cloud2)
%hold on
% show the shift in the initial images several times
num = 0;
for k = 1:4
num=num+1;
pause(.5)
figure(1), h1=imshow(C1)
xlabel('FIGURE 1')
F(num) = getframe(gcf);
%image(F.cdata)
%colormap(F.colormap)
pause(0.25)
figure(1), h2=imshow(C2)
xlabel('FIGURE 2')
num=num+1;
F(num) = getframe(gcf);
%image(F.cdata)
%colormap(F.colormap)
end
% Play the movie twenty times
%movie(F,20)
%%%% Set the template size %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% First calc the number of pixels in the shortest direction of the image (usually y direction)
MinSize = min(Cloud1_xsize, Cloud1_ysize); % number of pixels in shortest direction
%%% N is the minimum number of boxes in the shorter direction (usually y direction).
%%% In the shorter axis (usually y)there will be N-2 boxes analyzed.
%%% This is because the top and bottom boxes are considered too close to the edge to use.
%%% In the larger direction (usually x) there may be more boxes.
N = 6;
EdgeBoxSize = 1; % the number of edge boxes along each edge
TempWidth = floor(MinSize / N); % the pixel width of each template box
TempHeight = TempWidth; % make the template height and width the same size so corr part works good
%%% Now calculate the exact number of boxes in x and y directions
%%% This depends on the number of x versus y pixels.
Nx = floor(Cloud1_xsize/TempWidth);
Ny = floor(Cloud1_ysize/TempWidth);

How to plot colorful histogram type constellation diagram in Matlab

I would like to plot constellation diagram similar to the figure below.
.
My approach is something like this
clc;
clear all;
close all;
N=30000;
M=16;
Sr=randint(N,1,[0,(M-1)]);
S=qammod(Sr,16,0,'gray'); S=S(:);
Noisy_Data=awgn(S,20,'measured'); % Add AWGN
figure(2)
subplot(1,2,1)
plot(S,'o','markersize',10);
grid on
subplot(1,2,2)
plot(Noisy_Data,'.');
grid on
May you assist me to make necessary modification to get graph similar to the figure attached above. Thank you.
The first thing to do would be to compute a 2D histogram of your data. This can be done with the following:
% Size of the histogram matrix
Nx = 160;
Ny = 160;
% Choose the bounds of the histogram to match min/max of data samples.
% (you could alternatively use fixed bound, e.g. +/- 4)
ValMaxX = max(real(Noisy_Data));
ValMinX = min(real(Noisy_Data));
ValMaxY = max(imag(Noisy_Data));
ValMinY = min(imag(Noisy_Data));
dX = (ValMaxX-ValMinX)/(Nx-1);
dY = (ValMaxY-ValMinY)/(Ny-1);
% Figure out which bin each data sample fall into
IdxX = 1+floor((real(Noisy_Data)-ValMinX)/dX);
IdxY = 1+floor((imag(Noisy_Data)-ValMinY)/dY);
H = zeros(Ny,Nx);
for i=1:N
if (IdxX(i) >= 1 && IdxX(i) <= Nx && IdxY(i) >= 1 && IdxY(i) <= Ny)
% Increment histogram count
H(IdxY(i),IdxX(i)) = H(IdxY(i),IdxX(i)) + 1;
end
end
Note that you can play around with parameters Nx and Ny to adjust the desired resolution of the plot. Keep in mind that the larger the histogram, the more data samples (controlled by the parameter N of your simulation) you'll need to have enough data in the histogram bins to avoid getting a spotty plot.
You can then plot the histogram as a color map based on this answer. In doing so, you likely would want to add a constant to all non-zero bins of the histogram so that the white band is reserved for zero valued bins. This would provide a better correlation with the scatter plot. This can be done with:
% Colormap that approximate the sample figures you've posted
map = [1 1 1;0 0 1;0 1 1;1 1 0;1 0 0];
% Boost histogram values greater than zero so they don't fall in the
% white band of the colormap.
S = size(map,1);
Hmax = max(max(H));
bias = (Hmax-S)/(S-1);
idx = find(H>0);
H(idx) = H(idx) + bias;
% Plot the histogram
pcolor([0:Nx-1]*dX+ValMinX, [0:Ny-1]*dY+ValMinY, H);
shading flat;
colormap(map);
After increasing N to 1000000, this gives the following plot for the data generated according to your sample: