histogram of matrix with xlim - matlab

I have a m-by-n matrix of values between 10^-20 and 10^-8
I drew it by
figure();
hist(My_mat(:),15);
I obtain only one bins of the hist,also with '15' but I would to obtain several of bins between min and max values
Do you have any suggestions?

Indeed. To draw a histogram having arbitrary bins use:
nbins=10;
figure();
hist(data,nbins)
However, if no second argument is given the standard of 10 bins is used. I suspect your vector contains all identical numbers therefore yielding only a single column. Could you verify this?
Kind regards,
Ernst Jan

This works for me (I get 15 bins):
C=rand(300,600)*1e-20; % to have similar numbers as you have
nbins = 15;
hist(C(:),nbins);
If you still have problems, try
close all; clearvars;
before executing the rest.

Related

Memory-speed issues when doing a scatter plot in Matlab

I have the following memory-speed problem in Matlab and I would like your help to understand whether there may be a solution.
Consider the following 4 big column vectors X1, X2, Y1, Y2.
clear
rng default
P=10^8;
X1=rand(1,P)*5;
X2=rand(1,P)*5;
Y1=rand(1,P)*5;
Y2=rand(1,P)*5;
What I would like to do is a scatter plot where on the x-axis I have the sum between any possible two elements of X1 and X2 and on the y-axis I have the sum between any possible two elements of Y1 and Y2.
I post here three options I thought about that do not work mainly because of memory and speed issues.
Option 1 (issues: too slow when doing the loop, out of memory when doing vertcat)
Xtemp=cell(P,1);
Ytemp=cell(P,1);
for i=1:P
tic
Xtemp{i}=X1(i)+X2(:);
Ytemp{i}=Y1(i)+Y2(:);
toc
end
X=vertcat(Xtemp{:});
Y=vertcat(Ytemp{:});
scatter(X,Y)
Option 2 (issues: too slow when doing the loop, time increasing as the loop proceeds, Matlab going crazy and unable to produce the scatter even if I stop the loop after 5 iterations)
for i=1:P
tic
scatter(X1(i)+X2(:), Y1(i)+Y2(:))
hold on
toc
end
Option 3 (sort of giving up) (issues: as I increase T the scatter gets closer and closer to a square which is correct; I am wondering though whether this is caused by the fact that I generated the data using rand and in option 3 I use randi; maybe with my real data the scatter does not "converge" to the true plot as I increase T; also, what is the "optimal" T and R?).
T=20;
R=500;
for t=1:T
tic
%select R points at random from X1,X2,Y1,Y2
X1sel=(X1(randi(R,R,1)));
X2sel=(X2(randi(R,R,1)));
Y1sel=(Y1(randi(R,R,1)));
Y2sel=(Y2(randi(R,R,1)));
%do option 1 among those points and plot
Xtempsel=cell(R,1);
Ytempsel=cell(R,1);
for r=1:R
Xtempsel{r}=X1sel(r)+X2sel(:);
Ytempsel{r}=Y1sel(r)+Y2sel(:);
end
Xsel=vertcat(Xtempsel{:});
Ysel=vertcat(Ytempsel{:});
scatter(Xsel,Ysel, 'b', 'filled')
hold on
toc
end
Is there a way to do what I want or is simply impossible?
You are trying to build a vector with P^2 elements, i.e. 10^16. This is many order of magnitude more that what would fit into the memory of a standard computer (10GB is 10^10 bytes or 1.2 billion double precision floats).
For smaller vectors (i.e. P<1e4), try:
Xsum=bsxfun(#plus,X1,X2.'); %Matrix with the sum of any two elements from X1 and X2
X=X(:); %Reshape to vector
Ysum=bsxfun(#plus,Y1,Y2.');
Y=Y(:);
plot(X,Y,'.') %Plot as small dots, likely to take forever if there are too many points
To build a figure with a more reasonable number of pairs picked randomly from these large vectors:
Npick=1e4;
sel1=randi(P,[Npick,1]);
sel2=randi(P,[Npick,1]);
Xsel=X1(sel1)+X2(sel2);
Ysel=Y1(sel1)+Y2(sel2);
plot(Xsel,Ysel,'.'); %Plot as small dots

Dividing equally a vector matlab

in MFCCs i have specified f_low and f_high which are my frequency min and max bands, and i am about to compute N equally distanced mel values between these two frequency values. So i wrote
f_low=1000;
f_high=fs/2;
filt_num=26; % number of filters
stp=round(f_high/filt_num); % step
f=f_low:stp:f_high; % my frequency vector
but i can't divide equally my f vector, maybe there is a function in matlab that does it , or am i missing something? Please help and thanks in advance.
A bit of digging around leads me to believe you want a linearly spaced vector with filt_num entries, starting at f_low and ending at f_high. You should use linspace for that as follows:
f = linspace(f_low,f_high,filt_num);
This is essentially the same as your last two lines of code. Keep in mind your code only works when f_high is larger than f_low. linspace does not have this issue, as it also supports descending vectors.

How to plot this equation in MATLAB? Keep getting matrix dimension errors

The code I have is:
T=[0:0.1:24];
omega=((12-T)/24)*360;
alpha = [0:1:90];
latitude=35;
delta=[-23.45:5:23.45];
sind(alpha)=sind(delta).*sind(latitude)+cosd(delta).*cosd(latitude).*cosd(omega)
cosd(phi)=(sind(alpha).*sind(latitude)-cosd(delta))./(cosd(alpha).*cosd(latitude))
alpha represents my y-axis and is an angle between 0 and 90 degrees. phi represents my x-axis and is an angle between say -120 to +120. The overall result should look something like a half sine-wave.
Whenever I try to input that last line I get the error stating inner matrix dimensions must agree. So I tried to use reshape on my matrices for those variables I defined so that they work. But then I get '??? ??? Subscript indices must either be real positive integers or logicals.'
It seems very tedious to have to reshape my matrix every time I define a new set of variables in order to use them with an equation. Those variables are used for defining my axis range, is there a better way I can lay them out or an automatic command that will make sure they work every time?
I want to plot alpha and phi as a graph using something like
plot(alpha,phi)
but can't get past those errors? can't I just use a command that says something like define x-axis [0:90], define y-axis [-120:120] or something? I have spent far too much time on this problem and can't find a solution. I just want to plot the graph. Somebody please help! thanks.
Thanks
Here is a start for you:
% Latitude
L=35;
% Hour Angle
h = [-12:5/60:12];
w = 15*h;
% Initialize and clear plot window
figure(1); clf;
% Plot one day per month for half of the year
for N = 1:30:365/2
% Declination
d = 23.45*sind(360*(284+N)/365);
% Sun Height
alpha = asind(sind(L)*sind(d) + cosd(L)*cosd(d)*cosd(w));
% Solar Azimuth
x = ( sind(alpha)*sind(L)-sind(d) )./( cosd(alpha)*cosd(L) );
y = cosd(d)*sind(w)./cosd(alpha);
phi = real(atan2d(y,x));
% Plot
plot(phi,alpha); hold on;
end
hold off;
grid on;
axis([-180, 180, 0, 90]);
xlabel('Solar Azimuth')
ylabel('Solar Elevation')
The function asind is inherently limited to return values in the range of -90 to 90. That means that you will not get a plot that spans over 240 degrees like the one you linked to. In order for the plot to not have the inflection at +/- 90 degrees, you will need to find a way to infer the quadrant. Update: I added the cosine term to get an angle using atan2d.
Hopefully this will be enough to give you an idea of how to use Matlab to get the kind of result that you are after.
Element-wise multiplication (.*) and division ./, not the matrix versions:
sind(alpha)=sind(delta).*sind(latitude)+cosd(delta).*cosd(latitude).*cosd(omega)
cosd(phi)=(sind(alpha).*sind(latitude)-cosd(delta))./(cosd(alpha).*cosd(latitude))
But a bigger problem is that you can't index with decimal or non-positive values. Go back to the code before you got the subscript indices error. The indices "must either be real positive integers or logicals".
I think you're a bit confused about MATLAB sintax (as nispio mentioned). Maybe you want to do something like this?
T=[0:0.1:24];
omega=((12-T)/24)*360;
alpha = [0:1:90];
latitude=35;
delta=[-23.45:5:23.45];
[o1,d1]=meshgrid(omega,delta);
[a2,d2]=meshgrid(alpha,delta);
var1=sind(d1(:)).*sind(latitude)+cosd(d1(:)).*cosd(latitude).*cosd(o1(:));
var2=(sind(a2(:)).*sind(latitude)-cosd(d2(:)))./(cosd(a2(:)).*cosd(latitude));
plot(var1);hold on;plot(var2);
If not, you should post the algorithm or pseudocode

Plotting probability density function in matlab

I have a 1x4225 vector that its elements are between 0 and 1 and I want to plot their probability density function in matlab.
In the case of ksdensity() the problem is that the probability sometimes gets more than 1.
I also tried the code below to do that:
A= [1x4225];
xRange = 0:1;
N = hist(A,xRange);
plot(xRange,N./numel(A))
But because of huge number of my data it made an ambiguous plot that consists of some vertical lines and is useless for me.
So is there any way to solve this problem or any other way to do this in matlab that shows each element as a separate point in pdf plot ?
When you do xRange = 0:1; you get a 2-element vector [0 1]. That is probably not what you want. Specify a step like:
xRange = 0:0.01:1;
Plotting each element as a point is accomplished in MATLAB with the line specifier argument, like plot(xRange,N./numel(A),'*'). However, for a histogram with only a small number of bins, you might be better off with bar(...). If you go with a finer step, then plotting might be better.

Get absolute peak location in a vector in MATLAB

Suppose I have the A matrix like this:
A = [0,0,0,0,0,0,106,10,14,20,20,23,27,26,28,28,28,23,28,28,21,18,106,14,12,
17,16,15,22,19,20,18,21,23,23,18,17,15,106,28];
>> plot(A)
I want the index of the peaks in this dataset. The answer that I'm looking for in this example, is a matrix which contains those x value in your curve when you put the "data cursor" on absolute peaks.
The answer I want is: K = [7 23 39] which is the locations of the peaks.
When I use the plot command in MATLAB, the peaks are clearly visible. How can I find the x value of absolute peaks? Is it possible?
This does not give you all the peaks, but it gives you the maximum value in the set:
max_locations = find(A==max(A))
If you want to find the peaks, use the findpeaks function:
[peakVal,peakLoc]= findpeaks(A);
If you want maximum 5 or 10 peaks, use the following
[peakVal,peakLoc]= findpeaks(A,'sort','descend');