Inflection points are defined where the curve changes direction, and the derivative is equal to zero.
See if this does what you want:
x = [ 7.0 7.2 7.4 7.6 8.4 8.8 9.2 9.6 10.0];
y = [ 0.692 0.719 0.723 0.732 0.719 0.712 1.407 1.714 1.99];
dydx = gradient(y) ./ gradient(x);
zci = @(v) find(v(:).*circshift(v(:), [-1 0]) <= 0);
zxidx = zci(dydx);
for k1 = 1:numel(zxidx)
inflptx(k1) = interp1(dydx(zxidx(k1):zxidx(k1)+1), x(zxidx(k1):zxidx(k1)+1), 0, 'linear');
inflpty(k1) = interp1(x(zxidx(k1):zxidx(k1)+1), y(zxidx(k1):zxidx(k1)+1), inflptx(k1), 'linear');
end
figure(1)
plot(x, y)
hold on
plot(x, dydx)
plot(inflptx, inflpty, 'pg', 'MarkerFaceColor','g')
hold off
grid
legend('Data', 'Derivative', 'Inflection Points')
inflpts = regexp(sprintf('(%5.3f,%5.3f)\n', [inflptx; inflpty]), '\n', 'split');
text(inflptx, inflpty, inflpts(1:end-1),'FontSize',8, 'HorizontalAlignment','center', 'VerticalAlignment','bottom')
The ‘inflptx’ and ‘inflpty’ vectors (derived from a linear interpolation of the derivative) are the coordinates of the inflection points. They are approximate because your data are discrete. The code does not find an inflection point where what is apparently a spline interpolation might create one, because that is not in your original data.
EDIT — (8 Jun 2020 at 12:21)
While the original code works for the original data here, if the identified zero-crossings of the derivative are close to the ends of the vector, it will crash with indices that exceed the number of vector elements.
This version of the loop fixes that:
for k1 = 1:numel(zxidx)
ixrng = max(zxidx(k1)-2,1):min(zxidx(k1)+2,numel(x));
inflptx(k1) = interp1(dydx(ixrng), x(ixrng), 0, 'linear');
inflpty(k1) = interp1(x(ixrng), y(ixrng), inflptx(k1), 'linear');
end
The ‘inflpts’ assignment also needs to be modified:
inflpts = sprintfc('(%5.3f, %5.3f)', [inflptx; inflpty].');
text(inflptx, inflpty, inflpts,'FontSize',8, 'HorizontalAlignment','center', 'VerticalAlignment','bottom')
.
Best Answer