How to average values in plot, to make a plot with fewer values - matlab

I have a script that plots wind speed in m/s (measured every second) against time in minutes over a period of 24 hours. I want to make a new plot that instead of plotting wind speed each second, averages the wind speed over a period of 10 minutes and then plots this against the time.
Here is a sample image of my data:
Any ideas of how I can do this?

You can use a Moving Average filter using the smooth function as suggested by m.s. in a comment. This is fairly simple:
y = smooth(x,span);
This uses a symmetric smoothing filter, so the span (i.e. the number of samples it takes for smoothing) must be odd: take the current sample plus n before and n after the current sample. That way you still have one sample for every second, they are just smoothed to damp noise and measurement errors.
If you want to reduce the number of points, such that only one point every 10 minutes exists, you can do the following: You take the first 10min * 60s = 600 samples of the vector and put them in the first column of a new matrix. Then take the next 600 samples and put them in the second column, and so on. Now you can column-wise take the mean of the matrix. That way you have a new vector where every element is the mean of 600 samples.
In MATLAB this is easily possible:
X = reshape(x,600,[]); % create matrix with 600 elements per column
y = mean(X,1); % take column-wise mean

Related

Plotting x-axis and y-axis with different (indep) limits in Matlab

I developed an Android app such that each scan is set to 1 Minute, and during this time the sensor collects many many readings randomly. I want to plot one sensor data of one scan only as follows:
The time of the scan is put manually in seconds for only 1 minute (from 1:60 sec) in the x-axis. While the vector of random readings collected from the sensor (sometimes reach hundreds of values) in the y-axis.
How I can do this in Matlab?
I tried using this code but gives me an error. "Vectors must be the same length."
This is my code:
x1 = linspace(0,60);
plot(x1,vector1,'o-r',x1,vector2,'+-k','LineWidth',lw,'MarkerSize',msz);
xlabel('Time (s)');
ylabel('sensor readings')
In order to match the amount of values you have to modify the input for linspace:
x1 = linspace(0,60,length(vector1));
This way you will automatically get the right amount of entries for your x-axis vector.
You basically tell linspace to create a vector that ranges from 0 to 60 with length(vector1) entries, so that it matches the length of your data set.
Note that if your second data set has a different amount of entries as your first, you will need to create a different x-axis vector that respectively matches its amount of values.

'resample' to have the same size of signals

i have 4 (2 Rates and 2 Times) signals and i need to equalize their sizes. I cut them first off, because i need that too. Size of first time and rate signal is 3901, another 830. But not just to remove elements, i want to keep the curve. I thought i need interpolation and tried "resample" but it is not perfect. Looks like photo. How should i improve my codes? Any idea?
index=time >= 9.6 & tsyn <= 13.5; %time boundaries of first time signal
time1=tsyn(index); %first time signal
time_f=resample(time1,830,3901);
Rate1=CLU_YR1(index) %first rate signal
Rate_f=resample(Rate1,830,3901);
index2 = cm.Time.data >= 26.3 & cm.Time.data <= 30.45; %time boundaries of second time signal
time2=cm.Time.data(index2) %second time signal
Rat2=cm.BodySensor_SC1_Omega_B_z.data*(-180/pi) %second rate signal
Rate_p=Rat2(index2)
I suppose some of the misfit of your curves originates from the fact that the original sequence is not (close to) 0 at the end of the vector. From the matlab resample documentation:
When filtering, resample assumes that the input sequence, x, is zero before and after the samples it is given. Large deviations from zero at the endpoints of x can result in unexpected values for y.
What the best alternative is depends on what it is you want to do next. If you want to have a new, upsampled version (i.e. both signals of length 3901), you could look at interp1, which supports several different methods. If you choose to do this, keep in mind that the values in y(t) will be interpolated according to the values of t you provide. Since your time arrays do not seem to be aligned (one is between 9.6 and 13 sec, the other between 26 and 30), you are probably best off doing something along the lines of:
y_new = interp1( linspace(1,100,830), rate_p, linspace(1,100,3901), 'linear');
and the same for the time array.

Frequency from fft data set matlab [duplicate]

This question already has answers here:
How do I obtain the frequencies of each value in an FFT?
(5 answers)
Closed 6 years ago.
I have a data set in a matrix in matlab. It contains 25,000 values taken every 0.5 ns; so the total time of the dataset is 1.25E-5 seconds.
The data set contains very high frequency noise that I am not interested in so I create another matrix is every 50th data point from the first matrix So the size of the matrix is 1000*.
I plot the absolute values from matlab's fft this matrix (I also normalise the amplitude and only plot the first half) and get the attached (two plots, second is a close up of the low frequencies I am interested in). How do I convert the x-axis to frequency?
Another point, if I take every data point (so I create an fft of the entire 25,000 points) then the x-axis is exactly the same; in other words, the size of my matrix seems to have no bearing on the x-axis returned by matlab. I've attached two links to the frequency spectrum, one of which is a close-up of the low frequencies I am interested in. It's axis goes from 0-50, so it is these values I need to convert to Hz.
Thankyou in advance!
Close up of frequency spectrum
frequency spectrum
From what I read on http://www.mathworks.com/help/matlab/math/fast-fourier-transform-fft.html#bresqop-1, it appears that the units on the x-axis of the plotted FFT are Hz if the first vector, f, you put into the plot(f,power), is defined as a sequence of n elements (n being the number of data points put into the FFT) increasing from zero to the sample frequency.
Thus, for the first plot, which used every 50th of points that were taken at a frequency of 2 GHz, the sample frequency would be 40 MHz. Thus, f = (0:n-1)*4*10^7/(25000/50)
It goes on to show how to use the fftshift function to put the center of the output of the fft function at 0, but it's clear you already did that and chopped off the negative part.
So, once you have the right separation of fs/n, sampling frequency divided by number of data points used, in the vector that supplies the x-axis to the plot function, then the units of the x-axis will be Hz.
(I hope you still have the numbers to graph again? If not, this question might help: Confusion in figuring out the relation between actual frequency values and FFT plot indexes in MATLAB)

How to resample with interp1 in Matlab when input vectors are of different length

I have two variables in a .mat file here:
https://www.yousendit.com/download/UW13UGhVQXA4NVVQWWNUQw
testz is a vector of cumulative distance (in meters, monotonically and regularly increasing)
testSDT is a vector of integrated (cumulative) sound wave travel time (in milliseconds) generated using the distance vector and a vector of velocities
(there is an intermediate step of creating interval travel times)
Since velocity is a continuously variable function the resulting interval travelt times and also the integrated travel times are non integers and variable in magnitude
What I want is to resample the distance vector at regular time intervals (e.g. 1 ms, 2 ms, ..., n ms)
What makes it difficult is that the maximum travel time, 994.6659, is less than the number of samples in the 2 vectors, therefore it is not straightforward to use interp1.
i.e.:
X=testSDT -> 1680 samples
Y=testz -> 1680 samples
XI=[1:1:994] -> 994 samples
This is the code I've come up with. It is a working code and it is not too bad I think.
%% Initial chores
M=fix(max(testSDT));
L=(1:1:M);
%% Create indices
% this loops finds the samples in the integrated travel time vector
% that are closest to integer milliseconds and their sample number
for i=1:M
[cl(i) ind(i)] = min(abs(testSDT-L(i)));
nearest(i) = testSDT(ind(i));
end
%% Remove duplicates
% this is necessary to remove duplicates in the index vector (happens in this test).
% For example: 2.5 ms would be the closest to both 2 ms and 2 ms
[clsst,ia,ic] = unique(nearest);
idx=(ind(ia));
%% Interpolation
% this uses the index vectors to resample the depth vectors at
% integer times
newz=interp1(clsst,testz(idx),[1:1:length(idx)],'cubic')';
As far as I can see there is one issue with this code:
I rely on the vector idx as my XI for interpolation. Vector idx is 1 sample shorter than vector ind (one duplicate was removed).
Therefore my new times will stop one millisecond short. This is a very small issue, and duplicate are unlikely but I am wondering if anybody can think of a workaround, or of a different way to approach the problem altogether.
Thank you
If I understand you correctly, you want to extrapolate to that extra point.
you can do this is many ways, one is to add that extra point to the interp1 line.
If you have some function you expect to follow your data you can use it by fitting it to the data and then obtaining that extra point or with a tool like fnxtr.
But I have a problem understanding what you want because of the way you used the line. The third argument you use, [1:1:length(idx)], is just the series [1 2 3 ...], usually when interpolating, one uses some vector x_i of points of interest, though I doubt your points of interest happen to be the series of integers 1:length(idx), what you want is just [1:length(idx) xi], where xi is that extra point x-axis value.
EDIT:
Instead of the loop just produce matrix forms out of L and testSDT, then matrix operation is somewhat faster in doing the min(abs(...:
MM=ones(numel(testSDT),1)*L;
TT=testSDT*ones(1,numel(L));
[cl ind]=(min(abs(TT-MM)));
nearest=testSDT(ind);

FFT when data set has varying vector lengths

I have data from a model I am running. However the data is collected at each time step and there are varying numbers of time steps. It works out that although there are varying time steps, it is compensated by the change in time step so that all runs are running for the same time.
However I would think that when I have a vector that is 200 in length and one that is 900 in length, taking the FFT will give me inherently different frequencies. I feel like I should take the FFT with respect to the same time axis of all the samples.
The way I have the data now is just as row vectors were each entry is not associated with a space in time.
Is there a way to take the fft of each vector with respect to their place in a time axis rather than their place in the vector array?
My goal is to write a for loop and take the fft of many data sets, and then plot them to compare of frequency signatures change.
If you collect 200 samples in 1 second (200 Hz), you can resolve input data from 1 Hz (1/(1 sec)) to 100 Hz. If you sample for 1 second collecting 900 samples, you can resolve input from 1 Hz to 450 Hz. So both your samples have the same spacing (sampling in the frequency axis is 1 Hz), but they go up to different maximum frequencies!
If your issue is just about plotting, you can either throw away the high frequencies which are not available in all your plots:
totaltime=1; %# common total time of all datasets, in seconds
minsamplenumber=200;
figure;
hold all;
cutofffreq=((minsamplenumber/2+1)/totaltime);
freqscale=0:(1/totaltime):cutofffreq;
datasetcount=42;
ffts=NaN(minsamplenumber,datasetcount);
for i=1:datasetcount
data{i}=... %# collect your data; to make life easier always collect an even number..
ffts(:,i)=fft(data{i},minsamplenumber);
plot(freqscale,ffts{i}(1:end/2+1));
end
... or live with reality, and plot all data you have:
totaltime=1; %# common total time of all datasets, in seconds
figure;
hold all;
for i=1:42
data{i}=... %# collect your data; to make life easier always collect an even number..
ffts{i}=fft(data{i});
maxfreq(i)=((numel(ffts{i})/2+1)/totaltime);
freqscale{i}=0:(1/totaltime):maxfreq(i);
plot(freqscale{i},ffts{i}(1:end/2+1));
end
You could resample your data (by filtered interpolation) into constant length vectors where the sample rate was the same constant rate in each frame. You may have to overlap your FFT frames as well to get constant frame or window offsets.