Effacer les filtres
Effacer les filtres

Extract data from figure

1 vue (au cours des 30 derniers jours)
Anton Vernytsky
Anton Vernytsky le 8 Mar 2022
Commenté : Mathieu NOE le 16 Mar 2022
Hello,
i would like to write a code that will calculte the middle of the "bell'.For example y=1 it is the base off the "bell" and the local min point is the top of the "bell" and i need to find the middle of that "bell'' and draw a horizontal line.For example the base is y=1 and the top is y=0.9 so the middle will be line at y=0.95.
This is my code and example of what i want do draw(The red lines).
Thank you.
clear all;
clc;
xlsdata=xlsread('ForDataMining.xlsx');
Wavelength=xlsdata(2:2152);
for i=1:2
reflection = xlsdata(2:2152,i+1);
lmin = islocalmin(reflection,"MinSeparation",100);
bellheight=1-lmin;
bellmid=1-bellheight/2;
plot(Wavelength,reflection,Wavelength(lmin),reflection(lmin),'ro')
hold on
yline(bellmid);
hold off
title('Relative Reflectance-Wavelength')
xlabel('Wavelength[nm]')
ylabel('Relative Reflectance')
grid on
grid minor
figure(i)
end

Réponses (1)

Mathieu NOE
Mathieu NOE le 8 Mar 2022
hello Anton
I created some dummy data - as you didn't provide the excel file
here my suggestion, for one local minimum
clear all;
clc;
% some dummy data
Wavelength=1:1000;
reflection = min(ones(size(Wavelength)),1+0.37*sin(Wavelength/150+1.5));
lmin = islocalmin(reflection,"MinSeparation",100);
lmin_value = reflection(lmin);
bellheight=1-lmin_value;
bellmid=1-bellheight/2;
threshold = bellmid; %
[t0_pos,s0_pos,t0_neg,s0_neg]= crossing_V7(reflection,Wavelength,threshold,'linear'); % positive (pos) and negative (neg) slope crossing points
% ind => time index (samples)
% t0 => corresponding time (x) values
% s0 => corresponding function (y) values , obviously they must be equal to "threshold"
x_line = [t0_neg t0_pos];
y_line = threshold*ones(size(x_line));
figure(1)
plot(Wavelength,reflection,Wavelength(lmin),lmin_value,'ro',x_line,y_line,'r',t0_pos,s0_pos,'db',t0_neg,s0_neg,'dg','linewidth',2,'markersize',12);grid on
legend('signal','local min','threshold','positive slope crossing points','negative slope crossing points');
title('Relative Reflectance-Wavelength')
xlabel('Wavelength[nm]')
ylabel('Relative Reflectance')
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function [t0_pos,s0_pos,t0_neg,s0_neg] = crossing_V7(S,t,level,imeth)
% [ind,t0,s0,t0close,s0close] = crossing_V6(S,t,level,imeth,slope_sign) % older format
% CROSSING find the crossings of a given level of a signal
% ind = CROSSING(S) returns an index vector ind, the signal
% S crosses zero at ind or at between ind and ind+1
% [ind,t0] = CROSSING(S,t) additionally returns a time
% vector t0 of the zero crossings of the signal S. The crossing
% times are linearly interpolated between the given times t
% [ind,t0] = CROSSING(S,t,level) returns the crossings of the
% given level instead of the zero crossings
% ind = CROSSING(S,[],level) as above but without time interpolation
% [ind,t0] = CROSSING(S,t,level,par) allows additional parameters
% par = {'none'|'linear'}.
% With interpolation turned off (par = 'none') this function always
% returns the value left of the zero (the data point thats nearest
% to the zero AND smaller than the zero crossing).
%
% check the number of input arguments
error(nargchk(1,4,nargin));
% check the time vector input for consistency
if nargin < 2 | isempty(t)
% if no time vector is given, use the index vector as time
t = 1:length(S);
elseif length(t) ~= length(S)
% if S and t are not of the same length, throw an error
error('t and S must be of identical length!');
end
% check the level input
if nargin < 3
% set standard value 0, if level is not given
level = 0;
end
% check interpolation method input
if nargin < 4
imeth = 'linear';
end
% make row vectors
t = t(:)';
S = S(:)';
% always search for zeros. So if we want the crossing of
% any other threshold value "level", we subtract it from
% the values and search for zeros.
S = S - level;
% first look for exact zeros
ind0 = find( S == 0 );
% then look for zero crossings between data points
S1 = S(1:end-1) .* S(2:end);
ind1 = find( S1 < 0 );
% bring exact zeros and "in-between" zeros together
ind = sort([ind0 ind1]);
% and pick the associated time values
t0 = t(ind);
s0 = S(ind);
if ~isempty(ind)
if strcmp(imeth,'linear')
% linear interpolation of crossing
for ii=1:length(t0)
%if abs(S(ind(ii))) >= eps(S(ind(ii))) % MATLAB V7 et +
if abs(S(ind(ii))) >= eps*abs(S(ind(ii))) % MATLAB V6 et - EPS * ABS(X)
% interpolate only when data point is not already zero
NUM = (t(ind(ii)+1) - t(ind(ii)));
DEN = (S(ind(ii)+1) - S(ind(ii)));
slope = NUM / DEN;
slope_sign(ii) = sign(slope);
t0(ii) = t0(ii) - S(ind(ii)) * slope;
s0(ii) = level;
end
end
end
% extract the positive slope crossing points
ind_pos = find(sign(slope_sign)>0);
t0_pos = t0(ind_pos);
s0_pos = s0(ind_pos);
% extract the negative slope crossing points
ind_neg = find(sign(slope_sign)<0);
t0_neg = t0(ind_neg);
s0_neg = s0(ind_neg);
else
% empty output
ind_pos = [];
t0_pos = [];
s0_pos = [];
% extract the negative slope crossing points
ind_neg = [];
t0_neg = [];
s0_neg = [];
end
end
  2 commentaires
Mathieu NOE
Mathieu NOE le 8 Mar 2022
and now the multiple local minima code :
clear all;
clc;
close all
% some dummy data
Wavelength=1:1000;
reflection = min(ones(size(Wavelength)),1+0.55*sin(Wavelength/330).*sin(Wavelength/50+1.5));
lmin = islocalmin(reflection,"MinSeparation",100);
lmin_index = find(lmin);
lmin_value = reflection(lmin);
plot(Wavelength,reflection,Wavelength(lmin),lmin_value,'ro');
hold on
title('Relative Reflectance-Wavelength')
xlabel('Wavelength[nm]')
ylabel('Relative Reflectance')
for ci = 1:numel(lmin_value)
bellheight=1-lmin_value(ci);
bellmid=1-bellheight/2;
threshold = bellmid; %
[t0_pos,s0_pos,t0_neg,s0_neg]= crossing_V7(reflection,Wavelength,threshold,'linear'); % positive (pos) and negative (neg) slope crossing points
% ind => time index (samples)
% t0 => corresponding time (x) values
% s0 => corresponding function (y) values , obviously they must be equal to "threshold"
% keep closest t0_neg t0_pos values from lmin_value
[val,indd] = min(abs(lmin_index(ci)-t0_neg));
t0_neg_selected = t0_neg(indd);
[val,indd] = min(abs(lmin_index(ci)-t0_pos));
t0_pos_selected = t0_pos(indd);
x_line = [t0_neg_selected t0_pos_selected];
y_line = threshold*ones(size(x_line));
plot(x_line,y_line,'r','linewidth',2,'markersize',12);grid on
end
hold off
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function [t0_pos,s0_pos,t0_neg,s0_neg] = crossing_V7(S,t,level,imeth)
% [ind,t0,s0,t0close,s0close] = crossing_V6(S,t,level,imeth,slope_sign) % older format
% CROSSING find the crossings of a given level of a signal
% ind = CROSSING(S) returns an index vector ind, the signal
% S crosses zero at ind or at between ind and ind+1
% [ind,t0] = CROSSING(S,t) additionally returns a time
% vector t0 of the zero crossings of the signal S. The crossing
% times are linearly interpolated between the given times t
% [ind,t0] = CROSSING(S,t,level) returns the crossings of the
% given level instead of the zero crossings
% ind = CROSSING(S,[],level) as above but without time interpolation
% [ind,t0] = CROSSING(S,t,level,par) allows additional parameters
% par = {'none'|'linear'}.
% With interpolation turned off (par = 'none') this function always
% returns the value left of the zero (the data point thats nearest
% to the zero AND smaller than the zero crossing).
%
% check the number of input arguments
error(nargchk(1,4,nargin));
% check the time vector input for consistency
if nargin < 2 | isempty(t)
% if no time vector is given, use the index vector as time
t = 1:length(S);
elseif length(t) ~= length(S)
% if S and t are not of the same length, throw an error
error('t and S must be of identical length!');
end
% check the level input
if nargin < 3
% set standard value 0, if level is not given
level = 0;
end
% check interpolation method input
if nargin < 4
imeth = 'linear';
end
% make row vectors
t = t(:)';
S = S(:)';
% always search for zeros. So if we want the crossing of
% any other threshold value "level", we subtract it from
% the values and search for zeros.
S = S - level;
% first look for exact zeros
ind0 = find( S == 0 );
% then look for zero crossings between data points
S1 = S(1:end-1) .* S(2:end);
ind1 = find( S1 < 0 );
% bring exact zeros and "in-between" zeros together
ind = sort([ind0 ind1]);
% and pick the associated time values
t0 = t(ind);
s0 = S(ind);
if ~isempty(ind)
if strcmp(imeth,'linear')
% linear interpolation of crossing
for ii=1:length(t0)
%if abs(S(ind(ii))) >= eps(S(ind(ii))) % MATLAB V7 et +
if abs(S(ind(ii))) >= eps*abs(S(ind(ii))) % MATLAB V6 et - EPS * ABS(X)
% interpolate only when data point is not already zero
NUM = (t(ind(ii)+1) - t(ind(ii)));
DEN = (S(ind(ii)+1) - S(ind(ii)));
slope = NUM / DEN;
slope_sign(ii) = sign(slope);
t0(ii) = t0(ii) - S(ind(ii)) * slope;
s0(ii) = level;
end
end
end
% extract the positive slope crossing points
ind_pos = find(sign(slope_sign)>0);
t0_pos = t0(ind_pos);
s0_pos = s0(ind_pos);
% extract the negative slope crossing points
ind_neg = find(sign(slope_sign)<0);
t0_neg = t0(ind_neg);
s0_neg = s0(ind_neg);
else
% empty output
ind_pos = [];
t0_pos = [];
s0_pos = [];
% extract the negative slope crossing points
ind_neg = [];
t0_neg = [];
s0_neg = [];
end
end
Mathieu NOE
Mathieu NOE le 16 Mar 2022
hello Anton
if my submission has filled your expectations, do you mind accepting it ?
tx

Connectez-vous pour commenter.

Catégories

En savoir plus sur MATLAB Report Generator dans Help Center et File Exchange

Tags

Community Treasure Hunt

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

Start Hunting!

Translated by