interpolation of fortnightly annual temperature data into hourly measurements in matlab - matlab

I have a dataset of annual temperature measurements recorded at fortnightly intervals. The data looks similar to the following:
t = 1:14:365;
% GENERATE DATA
y = 1 + (30-1).*rand(1,length(t));
y1 = 20*sin(2*pi*t/max(t)); % Annual variation °C
y1(y1<0) = [];
tt = 365/14;
time = 1:tt:365;
plot(time,y1,'-o');
where it clearly follows a annual temperature cycle.
From this I am wondering if it is possible to add a sine function (which would represent a diurnal temperature range) onto the data? For example, from the fortnightly data, if we were to interpolate the series to have 8760 measurements i.e. hourly measurements, for the series to be believable it would need to be characterized by a diurnal temperature cycle in addition to the annual temperature cycle. Furthermore, the diurnal temperature cycle would need to be a function of the temperature measurements at that time i.e. would be greater in the summer than in winter. So maybe it would be better to firstly use linear interpolation to get the data to represents hourly intervals and then add the sine function. Is there a method for writing this into a script? or does anyone have an opinion on how to accurately achieve this?

You could first interpolate your data (down to 1 hours) using something like
x = 1:inv(24):365;
T_interp = interp1(t,y1,x,'spline');
Check out Matlab documentation for interp1 (example 2)
and then add a sine onto it. The following a sine of period 1 (24 hours) with amplitude A, with a minimum at 3am.
T_diurn = -A*sin(2*pi*x+(3/24)*2*pi);
Then
T_total = T_diurn + T_interp;

First: you know that good-looking plots are the most misleading things in existence? Interpolating data gathered every 14 days so that it will look like data collected every hour is considered at least bad practice most circles...
Having said that, I would use splines to do the interpolation -- they are a lot more flexible when it comes to changing from fortnightly and hourly to some arbitrary other combination, plus the annual temperature variation will be a lot smoother.
Here's how:
% Create spline through data
pp = spline(time, y1);
% define diurnal variation (this one is minimal at 4 AM)
T_diurn = #(t) -A*cos(2*pi*(t-(4/24)));
% plot example
t = 150 : 1/24 : 250;
plot( t, ppval(pp,t)+T_diurn(t) , 'b')

Related

getting the delay/lag of Ultrasonic pulse velocity matlab

I am currently doing a thesis that needs Ultrasonic pulse velocity(UPV). UPV can easily be attained via the machines but the data we acquired didn't have UPV so we are tasked to get it manually.
Essentially in the data we have 2 channels, one for the transmitter transducer and another for a receiver transducer.
We need to get the time from wave from the transmitter is emitted and the time it arrives to the receiver.
Using matlab, I've tried finddelay and xcorr but doesnt quite get the right result.
Here is a picture of the points I would want to get. The plot is of the transmitter(blue) and receiver(red)
So I am trying to find the two points in the picture but with the aid of matlab. The two would determine the time and further the UPV.
I am relatively a new MATLAB user so your help would be of great assistance.
Here is the code I have tried
[cc, lags] = xcorr(signal1,signal2);
d2 = -(lags(cc == max(cc))) / Fs;
#xenoclast hi there! so far the code i used are these.
close all
clc
Fs = input('input Fs = ');
T = 1/Fs;
L = input('input L = ');
t = (0:L-1)*T;
time = transpose(t);
i = input('input number of steploads = ');
% construct test sequences
%dataupv is the signal1 & datathesis is the signal2
for m=1:i
y1 = (dataupv(:,m) - mean(dataupv(:,m))) / std(dataupv(:,m));
y2 = (datathesis(:,m) - mean(datathesis(:,m))) / std(datathesis(:,m));
offset = 166;
tt = time;
% correlate the two sequences
[cc, lags] = xcorr(y2, y1,);
% find the in4dex of the maximum
[maxval, maxI] = max(cc);
[minval, minI] = min(cc);
% use that index to obtain the lag in samples
lagsamples(m,1) = lags(maxI);
lagsamples2(m,1) = lags(minI);
% plot again without timebase to verify visually
end
the resulting value is off by 70 samples compared to when i visually inspect the waves. the lag resulted in 244 but visually it should be 176 here are the data(there are 19 sets of data but i only used the 1st column) https://www.dropbox.com/s/ng5uq8f7oyap0tq/datatrans-dec-2014.xlsx?dl=0 https://www.dropbox.com/s/1x7en0x7elnbg42/datarec-dec-2014.xlsx?dl=0
Your example code doesn't specify Fs so I don't know for sure but I'm guessing that it's an issue of sample rate(s). All the examples of cross correlation start out by constructing test sequences according to a specific sample rate that they usually call Fs, not to be confused with the frequency of the test tone, which you may see called Fc.
If you construct the test signals in terms of Fs and Fc then this works fine but when you get real data from an instrument they often give you the data and the timebase as two vectors, so you have to work out the sample rate from the timebase. This may not be the same as the operating frequency or the components of the signal, so confusion is easy here.
But the sample rate is only required in the second part of the problem, where you work out the offset in time. First you have to get the offset in samples and that's a lot easier to verify.
Your example will give you the offset in samples if you remove the '/ Fs' term and you can verify it by plotting the two signals without a timebase and inspecting the sample positions.
I'm sure you've looked at dozens of examples but here's one that attempts to not confuse the issue by tying it to sample rates - you'll note that nowhere is it specified what the 'sample rate' is, it's just tied to samples (although if you treat the 5 in the y1 definition as a frequency in Hz then you will be able to infer one).
% construct test sequences
offset = 23;
tt = 0:0.01:1;
y1 = sin(2*pi*5*tt);
y2 = 0.8 * [zeros(1, offset) y1];
figure(1); clf; hold on
plot(tt, y1)
plot(tt, y2(1:numel(tt)), 'r')
% correlate the two sequences
[cc, lags] = xcorr(y2, y1);
figure(2); clf;
plot(cc)
% find the index of the maximum
[maxval, maxI] = max(cc);
% use that index to obtain the lag in samples
lagsamples = lags(maxI);
% plot again without timebase to verify visually
figure(3); clf; hold on
plot(y1)
plot(y2, 'r')
plot([offset offset], [-1 1], 'k:')
Once you've got the offset in samples you can probably deduce the required conversion factor, but if you have timebase data from the instrument then the inverse of the diff of any two consecutive entries will give it you.
UPDATE
When you correlate the two signals you can visualise it as overlaying them and summing the product of corresponding elements. This gives you a single value. Then you move one signal by a sample and do it again. Continue until you have done it at every possible arrangement of the two signals.
The value obtained at each step is the correlation, but the 'lag' is computed starting with one signal all the way over to the left and the other overlapping by only one sample. You slide the second signal all the way over until it's only overlapping the other end by a sample. Hence the number of values returned by the correlation is related to the length of both the original signals, and relating any given point in the correlation output, such as the max value, to the arrangement of the two signals that produced it requires you to do a calculation involving those lengths. The xcorr function makes this easier by outputting the lags variable, which tracks the alignment of the two signals. People may also talk about this as an offset so watch out for that.

Fourier Analysis - MATLAB

Good evening guys,
I wanna ask you a question regarding the analysis of a function in the domain of frequencies (Fourier). I have two vectors: one containing 7700 values for pressure, and the other one containing 7700 values (same number) for time.
For example, I call the firt vector "a" and the second one "b". With the command "figure(1),plot(a,b)" I obtain the curve in the domain of time.
How can I do to plot this curve in the domain of frequency, to make Fourier transform?
I've read about the function "fft", but I've not understood very well how it can be used...can anyone help me?
Thanks in advance for your attention!
fft returns spectrum as complex numbers. In order to analyze it you have to use its absolute value or phase. In general, it should look like this (let's assume that t is vector containing time and y is the one with actual signal, N is the number of samples):
fY = fft(y) / (N/2) % scale it to amplitude, typically by N/2
amp_fY = abs(fY)
phs_fY = angle(fY)
Additionally, it would be nice to have FFT with known frequency resolution. For that, you need sampling period/frequency. Let's call that frequency fs:
fs = 1/(t(1) - t(0))
and the vector of frequencies for FFT (F)
should be:
F = (0:fs/N:(N-1)*fs/N)
and finally plots:
plot(F, amp_fY)
% or plot(F, phs_fy) according to what you need
I you can use stem instead of plot to get some other type of chart.
Note that the DC component (the average value) will be doubled on the plot.
Hope it helps

analyse time series at a specific frequency

I have a long data set of water temperature:
t = 1/24:1/24:365;
y = 1 + (30-1).*rand(1,length(t));
plot(t,y)
The series extends for one year and the number of measurements per day is 24 (i.e. hourly). I expect the water temperature to follow a diurnal pattern (i.e. have a period of 24 hours), therefore I would like to evaluate how the 24 hour cycle varies throughout the year. Is there a method for only looking at specific frequencies when analyzing a signal? If so, I would like to draw a plot showing how the 24 hour periodicity in the data varies through the year (showing for example if it is greater in the summer and less in the winter). How could I do this?
You could use reshape to transform your data to a 24x365 matrix. In the new matrix every column is a day and every row a time of day.
temperature=reshape(y,24,365);
time=(1:size(temperature,1))-1;
day=(1:size(temperature,2))-1;
[day,time]=meshgrid(day,time);
surf(time,day,temperature)
My first thought would be fourier transformation. This will give you a frequency spectrum.
At high frequencies (> 1/d) you would have the pattern for a day, at low frequencies the patter over longer times. (see lowpass and highpass filter)
Also you could go for a frequency/time visualization that will show how the frequencies change over a year.
A bit more work - but you could write a simple model and create a Kalman filter for it.

generate signal with seasonal and diurnal component

This is a rather vague question but here we go - I would like to generate a time series for hourly measurements of one year, so for 2011 ti would 8760 values within the series. To make it easier to understand what I am trying to do I will use a real world example:
If we had a time series of hourly air temperature measurements an then plotted the entire series it would look similar to a bell shaped curve i.e.
a = 0; b = 30;
x = a + (b-a) * rand(1, 8760);
m = (a + b)/2;
s = 12;
p1 = -.5 * ((x - m)/s) .^ 2;
p2 = (s * sqrt(2*pi));
f = exp(p1) ./ p2;
plot(x,f,'.')
with the maximum values occurring in mid summer and lowest values during the winter. However, by zooming in on specific days we would see that the temperature also fluctuates between the day and the evening where maximum temperatures would occur at approximately 15:00 and minimum temperature at approximately 06:00.
So, my question is how would I generate this series, i.e. a time series which had a maximum value of say 30 degrees in mid summer i.e. value (8760/2) and also had the daily pattern mentioned above incorporated into the overall pattern?
The obvious way to do this would be to add together 2 sine waves, one for the diurnal variations and one for the annual variations.
Whether or not a sine wave is close enough to a bell-shaped curve for your liking I don't know, but I could make a vague argument that since the variation in annual and diurnal temperatures is (in part) a product of (approximately) circular motions you should be using sine waves anyway.
If you need help generating the sine waves update your question.
If I understand the question correctly, you'd like to have a superposition of the two series of known shape, right? If so, you just have to add them up. The important part is to shift the daily temperature fluctuation signal so that its mean is 0, provided the "year" curve expresses the average temperature.

Using FFT in MATLAB on multiple matrices of data to find differences within responses

I have 4 matrices of data F1,F2,O1,O2. All are neural signals collected at 1ms for a second. F1 and O1 were collected at the same time as with F2 and O2. I need to find how the data collected differes between the 2 trials and also compare the components of each trial (F1 and O1) to each other to notice and differences in respones. I'm new to MATLAB but I believe I need to use the fft function. I'm just not sure where to start, any help would be greatly appeciated.
Based on your sampling rate (1000 times per second), you will only be able to analyze signals which have frequency of up to 500 hz. Any neural signal components which have higher components will appear as signals of lower components (unless your device has highpass filter etc..)
The command for fft from Matlab Help is:
Y = fft(signal, n)
Signal is either F1 or O1 or F2 or O2 and should be a vector 1000 long. n determines how many samples your FFT have. This is essentially how finely you will split up the frequency values between 0 hz and 1000 hz (your sampling rate). For example, if you choose n =256, your Y will be a 256 long vector with a measure corresponding to the frequencies (0*1000/256 hz, 1*1000/256 hz, ... 255*1000/256 hz).
Y will be a vector of complex values. Often, you want to see the strength or power of the signal. You can use 'abs()' to find the magnitude. myPSD = abs(Y). Next because your signals are real signals, their fft's are symmetric about half the sampling rate (500hz). Thus, you should only look at the first half. Here is a code snippet to look at the first half.
Y = fft(signal, n); % choose your n
myPSD = abs(Y);
myHalfPSD = myPSD(1:ceil(n/2))
myFreqValues = [0:1000/n:500-1000/n] % both myHalfPSD and myFreqValues should be n/2 long
plot(myFreqValues, myHalfPSD)
Typically, PSD is displayed on a log scale or even decibal. So you might add a line.
Y = fft(signal, n); % choose your n
myPSD = abs(Y);
myHalfPSD = myPSD(1:ceil(n/2))
myHalfDBPSD = 20*log(myHalfPSD)
myFreqValues = [0:1000/n:500-1000/n] % both myHalfPSD and myFreqValues should be n/2 long
plot(myFreqValues, myHalfDBPSD)
If you want to plot all 4 graphs at once you might want to use something like
subplot(4,1,1), subplot(4,1,2) etc..
Hope that helps,
Chuan
If you're trying to compare the frequency spectrums of two separate acquisitions, then fft is the tool you want to use.
Mathworks has pretty good documentation on how to use the fft function, and you can probably cut and paste your data right into the example code they provide.
If you want to plot the data on the same axes, you can use the hold on command, plot different line colors (Ex: plot(x,y,'r') will plot a red line, 'b' a blue one, etc. - see lineseries properties) and include a legend to label the plots.