MATLAB: find peaks from data iterations - matlab

I have a function that plots the magnitude of an fft function from a signal.
For every iteration I want to determine the x-value of the two peaks below 2000. I thought this was relatively simple using the function findpeaks however it has not given me the correct output.
I do not intend to plot the ouput, but just for illustration purposes here is a plot. I only want to know the peaks for the data below 2000 (the first set of peaks)
Example of one iteration:
Here is a bit of my code. B is a vector containing the starting indices for every segment of data that needs to be analysed.
function [number] = fourir_(data,sampling_rate)
%Finds the approximate starting index of every peak segment
%B is a vector containing the indeces
[A,B] = findpeaks(double(abs(data) > 0.6), 'MinPeakDistance', 2500);
Fs = sampling_rate;
t = 0:1/Fs:0.25;
C = zeros(size(B),2)
for i = 1:numel(B)
new_data = data(B(i):(B(i)+200))
y = double(new_data)/max(abs(new_data));
n = length(y);
p = abs(fft(y));
f = (0:n-1)*(Fs/n);
end
Example data: https://www.dropbox.com/s/zxypn3axoqwo2g0/signal%20%281%29.mat?dl=0

Here is your answer, this is exactly what #Ed Smith suggested in his first comment. You can just add a threshold in order to distinguish the major peak.
%Finds the approximate starting index of every peak segment
%B is a vector containing the indeces
[A,B] = findpeaks(double(abs(data) > 0.6), 'MinPeakDistance', 2500);
Fs = sampling_rate;
t = 0:1/Fs:0.25;
C = zeros(size(B),2)
for i = 1:numel(B)
new_data = data(B(i):(B(i)+200))
y = double(new_data)/max(abs(new_data));
n = length(y);
p = abs(fft(y));
f = (0:n-1)*(Fs/n);
p1 = p(1:round(length(p)/2));
p1(p1<10) = 0; %add a threshold
[~,ind] = findpeaks(p1); %index of where are the peaks
C(i,:) = f(ind);
hold on
plot(f,p,'b',C(i,:),p(ind),'ro')
end

The following may help, which seems to get the peaks from one fft of your signal data,
clear all
close all
%load sample data from https://www.dropbox.com/s/zxypn3axoqwo2g0/signal%20%281%29.mat?dl=0
load('./signal (1).mat')
%get an FFT and take half
p = abs(fft(signal));
p = p(1:length(p)/2);
%find peaks and plot
[pk, loc] = findpeaks(p,'MINPEAKHEIGHT',100,'MINPEAKDISTANCE',100);
plot(p,'k-')
hold all
plot(loc, pk, 'rx')
which looks like,
Where some of the peaks are isolated...

Related

Potting sampling result frequency in histogram

I am just starting to learn Matlab.
Case:
From 3 elements, let's say 1,2, and 3. I want to sample 2 elements randomly. I want to simulate it 100 times to see the probability of the outcomes pair.
How can I plot the result on histogram that I can visualize the frequency of each pair. So far, I can do the sampling :
for i=1:100
datasample(1:3,2,'Replace',true)
end
So possible outcome is (1,1),(1,2),(2,1),(2,3), etc.
How can I plot the frequency of the outcome using histogram?
Thanks in advance
n = 100;
% generate data random
arr = zeros(n, 2);
for i = 1:n
arr(i, :) = randi([1,3],1,2);
end
% frequency
[ii, jj, kk] = unique(arr, 'rows', 'stable');
f = histc(kk, 1:numel(jj));
result = [ii f];
% plot
cuts = strcat(num2str(result(:,1)), '-',num2str(result(:,2)));
bar(result(:,3))
grid on
xlabel('combination')
ylabel('frequency')
set(gca,'xticklabel',{cuts});
set(gca,'XTickLabelRotation',45);

Issue with Discrete Double Fourier Series in MATLAB

The formula for the discrete double Fourier series that I'm attempting to code in MATLAB is:
The coefficient in front of the trigonometric sum (Fourier amplitude) is what I'm trying to extract from the fitting of the data through the double Fourier series seen above. Using my current code, the original function is not reconstructed, therefore my coefficients cannot be correct. I'm not certain if this is of any significance or insight, but the second term for the A coefficients (Akn(1))) is 13 orders of magnitude larger than any other coefficient.
Any suggestions, modifications, or comments about my program would be greatly appreciated.
%data = csvread('digitized_plot_data.csv',1);
%xdata = data(:,1);
%ydata = data(:,2);
%x0 = xdata(1);
lambda = 20; %km
tau = 20; %s
vs = 7.6; %k/s (velocity of CHAMP satellite)
L = 4; %S
% Number of terms to use:
N = 100;
% set up matrices:
M = zeros(length(xdata),1+2*N);
M(:,1) = 1;
for k=1:N
for n=1:N %error using *, inner matrix dimensions must agree...
M(:,2*n) = cos(2*pi/lambda*k*vs*xdata).*cos(2*pi/tau*n*xdata);
M(:,2*n+1) = sin(2*pi/lambda*k*vs*xdata).*sin(2*pi/tau*n*xdata);
end
end
C = M\ydata;
%least squares coefficients:
A0 = C(1);
Akn = C(2:2:end);
Bkn = C(3:2:end);
% reconstruct original function values (verification check):
y = A0;
for k=1:length(Akn)
y = y + Akn(k)*cos(2*pi/lambda*k*vs*xdata).*cos(2*pi/tau*n*xdata) + Bkn(k)*sin(2*pi/lambda*k*vs*xdata).*sin(2*pi/tau*n*xdata);
end
% plotting
hold on
plot(xdata,ydata,'ko')
plot(xdata,yk,'b--')
legend('Data','Least Squares','location','northeast')
xlabel('Centered Time Event [s]'); ylabel('J[\muA/m^2]'); title('Single FAC Event (50 Hz)')

Plotting a collection of sine waves

I have the following code:
Fs = 1000;
T = 1/Fs;
L = 1000;
t = (0:L-1)*T;
k = 25:1:50;
m = 1:1:25;
where k and m are corresponding. I want to plot the 25 sine waves resulting from:
x = m*sin(2*pi*k*t);
I thought about doing it using a for loop that takes one value from m and k each time, but I'm unsure how to proceed.
Below is a very basic plotting solution. You will notice that it's very difficult to see what's going on in the plot, so you might want to consider other ways to present this data.
function q45532082
Fs = 1000;
T = 1/Fs;
L = 1000;
t = (0:L-1)*T;
k = 26:1:50;
m = 1:1:25;
%% Plotting
assert(numel(m) == numel(k)); % We make sure that the number of elements is the same.
figure(); hold on; % "hold" is needed if you want to see all curves at the same time.
for ind1 = 1:numel(m)
plot(t,m(ind1)*sin(2*pi*k(ind1)*t));
end
This is the result:
Note that the number of elements in k and m in your code is different, so I had to change it.
Using the functionality of plot you can also plot all sine waves without a loop:
Fs = 1000;
T = 1/Fs;
L = 1000;
t = (0:L-1)*T;
k = 26:1:50;
m = 1:1:25;
x = m.*sin(2.*pi.*bsxfun(#times,t.',k)); %this results in an L*25 matrix, each column is data of one wave
% or, if you have version 2016b or newer:
% x = m.*sin(2.*pi.*t.'*k);
plot(t,x) % plot all sines at ones
and as #Dev-iL noted, I also had to change k.
The result with L = 1000 is too crowded, so I plot it here with L = 50:

Morlet wavelet transformation function returns nonsensical plot

I have written a matlab function (Version 7.10.0.499 (R2010a)) to evaluate incoming FT signal and calculate the morlet wavelet for the signal. I have a similar program, but I needed to make it more readable and closer to mathematical lingo. The output plot is supposed to be a 2D plot with colour showing the intensity of the frequencies. My plot seems to have all frequencies the same per time. The program does make an fft per row of time for each frequency, so I suppose another way to look at it is that the same line repeats itself per step in my for loop. The issue is I have checked with the original program, which does return the correct plot, and I cannot locate any difference beyond what I named the values and how I organized the code.
function[msg] = mile01_wlt(FT_y, f_mn, f_mx, K, N, F_s)
%{
Fucntion to perform a full wlt of a morlet wavelett.
optimization of the number of frequencies to be included.
FT_y satisfies the FT(x) of 1 envelope and is our ft signal.
f min and max enter into the analysis and are decided from
the f-image for optimal values.
While performing the transformation there are different scalings
on the resulting "intensity".
Plot is made with a 2D array and a colour code for intensity.
version 05.05.2016
%}
%--------------------------------------------------------------%
%{
tableofcontents:
1: determining nr. of analysis f, prints and readies f's to be used.
2: ensuring correct orientation of FT_y
3:defining arrays
4: declaring waveletdiagram and storage of frequencies
5: for-loop over all frequencies:
6: reducing file to manageable size by truncating time.
7: marking plot to highlight ("randproblemer")
8: plotting waveletdiagram
%}
%--------------------------------------------------------------%
%1: determining nr. of analysis f, prints and readies f's to be used.
DF = floor( log(f_mx/f_mn) / log(1+( 1/(8*K) ) ) ) + 1;% f-spectre analysed
nr_f_analysed = DF %output to commandline
f_step = (f_mx/f_mn)^(1/(DF-1)); % multiplicative step for new f_a
f_a = f_mn; %[Hz] frequency of analysis
T = N/F_s; %[s] total time sampled
C = 2.0; % factor to scale Psi
%--------------------------------------------------------------%
%2: ensuring correct orientation of FT_y
siz = size(FT_y);
if (siz(2)>siz(1))
FT_y = transpose(FT_y);
end;
%--------------------------------------------------------------%
%3:defining arrays
t = linspace(0, T*(N-1)/N, N); %[s] timespan
f = linspace(0, F_s*(N-1)/N, N); %[Hz] f-specter
%--------------------------------------------------------------%
%4: declaring waveletdiagram and storage of frequencies
WLd = zeros(DF,N); % matrix of DF rows and N columns for storing our wlt
f_store = zeros(1,DF); % horizontal array for storing DF frequencies
%--------------------------------------------------------------%
%5: for-loop over all frequencies:
for jj = 1:DF
o = (K/f_a)*(K/f_a); %factor sigma
Psi = exp(- 0*(f-f_a).*(f-f_a)); % FT(\psi) for 1 envelope
Psi = Psi - exp(-K*K)*exp(- o*(f.*f)); % correctional element
Psi = C*Psi; %factor. not set in stone
%next step fits 1 row in the WLd (3 alternatives)
%WLd(jj,:) = abs(ifft(Psi.*transpose(FT_y)));
WLd(jj,:) = sqrt(abs(ifft(Psi.*transpose(FT_y))));
%WLd(jj,:) = sqrt(abs(ifft(Psi.*FT_y))); %for different array sizes
%and emphasizes weaker parts.
%prep for next round
f_store (jj) = f_a; % storing used frequencies
f_a = f_a*f_step; % determines the next step
end;
%--------------------------------------------------------------%
%6: reducing file to manageable size by truncating time.
P = floor( (K*F_s) / (24*f_mx) );%24 not set in stone
using_every_P_point = P %printout to cmdline for monitoring
N_P = floor(N/P);
points_in_time = N_P %printout to cmdline for monitoring
% truncating WLd and time
WLd2 = zeros(DF,N_P);
for jj = 1:DF
for ii = 1:N_P
WLd2(jj,ii) = WLd(jj,ii*P);
end
end
t_P = zeros(1,N_P);
for ii = 1:N_P % set outside the initial loop to reduce redundancy
t_P(ii) = t(ii*P);
end
%--------------------------------------------------------------%
%7: marking plot to highlight boundary value problems
maxval = max(WLd2);%setting an intensity
mxv = max(maxval);
% marks in wl matrix
for jj= 1:DF
m = floor( K*F_s / (P*pi*f_store(jj)) ); %finding edges of envelope
WLd2(jj,m) = mxv/2; % lower limit
WLd2(jj,N_P-m) = mxv/2;% upper limit
end
%--------------------------------------------------------------%
%8: plotting waveletdiagram
figure;
imagesc(t_P, log10(f_store), WLd2, 'Ydata', [1 size(WLd2,1)]);
set(gca, 'Ydir', 'normal');
xlabel('Time [s]');
ylabel('log10(frequency [Hz])');
%title('wavelet power spectrum'); % for non-sqrt inensities
title('sqrt(wavelet power spectrum)'); %when calculating using sqrt
colorbar('location', 'southoutside');
msg = 'done.';
There are no error message, so I am uncertain what exactly I am doing wrong.
Hope I followed all the guidelines. Otherwise, I apologize.
edit:
my calling program:
% establishing parameters
N = 2^(16); % | number of points to sample
F_s = 3.2e6; % Hz | samplings frequency
T_t = N/F_s; % s | length in seconds of sample time
f_c = 2.0e5; % Hz | carrying wave frequency
f_m = 8./T_t; % Hz | modulating wave frequency
w_c = 2pif_c; % Hz | angular frequency("omega") of carrying wave
w_m = 2pif_m; % Hz | angular frequency("omega") of modulating wave
% establishing parameter arrays
t = linspace(0, T_t, N);
% function variables
T_h = 2*f_m.*t; % dimless | 1/2 of the period for square signal
% combined carry and modulated wave
% y(t) eq. 1):
y_t = 0.5.*cos(w_c.*t).*(1+cos(w_m.*t));
% y(t) eq. 2):
% y_t = 0.5.*cos(w_c.*t)+0.25*cos((w_c+w_m).*t)+0.25*cos((w_c-w_m).*t);
%square wave
sq_t = cos(w_c.*t).*(1 - mod(floor(t./T_h), 2)); % sq(t)
% the following can be exchanged between sq(t) and y(t)
plot(t, y_t)
% plot(t, sq_t)
xlabel('time [s]');
ylabel('signal amplitude');
title('plot of harmonically modulated signal with carrying wave');
% title('plot of square modulated signal with carrying wave');
figure()
hold on
% Fourier transform and plot of freq-image
FT_y = mile01_fftplot(y_t, N, F_s);
% FT_sq = mile01_fftplot(sq_t, N, F_s);
% Morlet wavelet transform and plot of WLdiagram
%determining K, check t-image
K_h = 57*4; % approximation based on 1/4 of an envelope, harmonious
%determining f min and max, from f-image
f_m = 1.995e5; % minimum frequency. chosen to showcase all relevant f
f_M = 2.005e5; % maximum frequency. chosen to showcase all relevant f
%calling wlt function.
name = 'mile'
msg = mile01_wlt(FT_y, f_m, f_M, K_h, N, F_s)
siz = size(FT_y);
if (siz(2)>siz(1))
FT_y = transpose(FT_y);
end;
name = 'arnt'
msg = arnt_wltransf(FT_y, f_m, f_M, K_h, N, F_s)
The time image has a constant frequency, but the amplitude oscillates resempling a gaussian curve. My code returns a sharply segmented image over time, where each point in time holds only 1 frequency. It should reflect a change in intensity across the spectra over time.
hope that helps and thanks!
I found the error. There is a 0 rather than an o in the first instance of Psi. Thinking I'll maybe rename the value as sig or something. besides this the code works. sorry for the trouble there

MATLAB: Multiple occurences data in the pdist function: how?

MATLAB: we have data that give x y coordinates of occurences. Often there are more then 1 occurences on one location. This generates a problem when we want to use this data in the function pdist. We tried to change the data into a list with x y coordinates for EACH occurence, but havent managed so far. Does anyone have a solution for this?
% initial values m = 0;
[X,Y,People,Positive] = textread('Loaloa_data.txt', '%f%f%f%f', 'headerlines', 1);
LoaData = [X,Y,People, Positive];
%calculate percentage of infected people per location
Percentage_per_Location = (Positive(:)./People(:))*100;
%calculate percentage of total infected people per location
TotPos = sum(Positive);
Percentage_of_Total = Positive(:)./TotPos*100;
LoaData = [X,Y,People,Positive,Percentage_per_Location, Percentage_of_Total];
%Make a new frequency table in which every value of Positive has a x and y
%value.
% first make a new matrix with x and y coordinated and positive values.
LengthColumn = (1:197)';
Matrix1 = [LengthColumn,X,Y,Positive];
Freq = zeros(sum(Positive(:)),2) ;
% r = Matrix1(:,1)
% CumFreq = ([1: sum(Positives)]);
% Freq = Matrix1(:,4);
% xyData =zeros(length(Freq),2);
for i=1:length(Matrix1(:,1))
%for m<=TotPos
F = Matrix1(i,4)
for j =[1:F]
m = m+j
Freq(m,1:2) = Matrix1(i,2:3)
end
% end
end