Clear Filters
Clear Filters

How to fit a sine curve with only the maximum and minimum values

17 views (last 30 days)
Hi, I am trying to plot a sine wave through the high and low water points from a measuring station in the North Sea.
The image shows the first few data points. I've tried fitting a curve, filling the gaps etc. but I can't get Matlab to acknowledge the oscillating signal.
Help will be appreciated, thank you!
this is the goal:
Sam Chak
Sam Chak on 8 Apr 2024
It might be easier to fit a custom sinusoidal waveform if the data is converted to the unit of 'seconds'. However, it is important to note that the time step in the t vector is not uniform.
where and are the time-varying amplitude and the time-varying period of the sine wave, respectively.
T = readtable("datapoints.xlsx", VariableNamingRule="preserve")
T = 58x2 table
t_datetime t_datenum ____________________ _________ 01-Jan-2022 03:05:00 -1.3 01-Jan-2022 09:02:00 1.5 01-Jan-2022 15:32:00 -1.4 01-Jan-2022 21:34:00 1.4 02-Jan-2022 04:08:00 -1.4 02-Jan-2022 10:06:00 1.5 02-Jan-2022 16:31:00 -1.4 02-Jan-2022 22:29:00 1.5 03-Jan-2022 05:03:00 -1.6 03-Jan-2022 11:04:00 1.5 03-Jan-2022 17:24:00 -1.4 03-Jan-2022 23:20:00 1.6 04-Jan-2022 05:56:00 -1.6 04-Jan-2022 11:59:00 1.5 04-Jan-2022 18:16:00 -1.4 05-Jan-2022 00:09:00 1.7
x = T{:,1}; % datetime data
t = seconds(x - x(1)); % convert to seconds
A = T{:,2}; % high and low points of the sea level
stem(t, A), grid on, xlabel('Time (sec)'), ylabel('Sea level')
title('Sea level around the North Sea from 1st to 15th, Jan 2022')

Sign in to comment.

Answers (2)

Bruno Luong
Bruno Luong on 8 Apr 2024
Edited: Bruno Luong on 8 Apr 2024
piecewise (co)sine interpolation (not fitting).
I don't think you have extra DOF to play with if you restrict data to be local extrema and model follows a sinusoidal law.
data = readtable('');
dt = t-t(1);
y = data.t_datenum;
dti = linspace(min(dt),max(dt),1025);
yi = sininterp(dt, y, dti); % function defined below
% Ploy check result
dtfun = @(dt) datetime(dt+t(1),'ConvertFrom','datenum');
h = plot(dtfun(dt),y,"ob",dtfun(dti),yi,"r");
% zoom plot
ax2 = subplot(2,1,2);
h = plot(dtfun(dt),y,"ob",dtfun(dti),yi,"r");
xlim(ax2, dtfun([8 11]))
function yi = sininterp(t, y, ti)
ti = ti(:);
i = discretize(ti, t);
yi = nan(size(ti));
valid = i>=1 & i<numel(ti);
i = i(valid);
y1 = y(i);
y2 = y(i+1);
ym = (y1+y2)/2;
A = (y1-y2)/2;
alpha = (ti(valid) - t(i)) .* (pi./(t(i+1)-t(i)));
yi(valid) = ym + A.*cos(alpha);

R on 8 Apr 2024
Hi Particia,
Fitting a piecewise cubic Hermite ("pchip") curve might help with this use case. Here is an example of the same
% Read data from Excel file
data = readtable('datapoints.xlsx');
% Convert first column to string array for time labels
time = string(table2array(data(:, 1)));
% Extract water level data from second column
waterLevel = table2array(data(:, 2));
% Create index array for plotting
x=(1:58)'; % Ensure x is a column vector
% Plot water level data
title('Water Level vs. Time');
xticklabels(time) % Set custom x-axis tick labels
% Fit a piecewise cubic Hermite interpolating polynomial
[curve,gof,output] = fit(x,waterLevel,"pchipinterp");
% Overlay fitted curve on the plot
hold on
hold off
Here is the plot I get after executing the above code:
Refer to the following link to learn more about 'pchipinterp' curve fitting model:
You can also find a list of curve fitting models that MATLAB supports in the following documentation:

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!