How to find x-values when y-function equals a set value?

Hi, there!
New to matlab.. I have a dilema trying to find the x-values for a function =0.7(see figure). And I should be able to find both values of x when the bell-curve changes.
Big help, please! I've tried fzero, and other functions and mostly does't work or it will just give me one single value of x. there should always be 2.
Thank you in advance!
x=[0.46 0.7]
f=(a1*exp(-((x-b1)/c1).^2))=0.7
The a1, b1 and c1 values are known.

 Accepted Answer

Try this:
x = linspace(0.54, 0.61); % Create Data
y = exp(-(x-0.58).^2*1E+4); % Create Data
idx = find(diff(sign(y-0.7)));
for k = 1:numel(idx)
idxrng = [-1 1]+idx(k);
x7(k) = interp1(y(idxrng), x(idxrng), 0.7); % Interpolate To Find Intersection ‘x’-Value
end
figure
plot(x, y)
hold on
plot(xlim, [1 1]*0.7, ':k', 'LineWidth',1) % Reference Line
plot(x7, [1 1]*0.7, 'pg','MarkerFaceColor','g','MarkerSize',10) % Intersections
plot([1 1]*x7(1), [min(ylim) 0.7], ':k')
plot([1 1]*x7(2), [min(ylim) 0.7], ':k')
hold off
legend('Data','Reference','Intersections', 'Location','NW')
Use your own function for ‘y’. I would have used it, however the parameters are nowhere to be found.
EDIT — (18 Oct 2020 at 19:37)
Added plot image —
.

7 Comments

Hi, thank you so much for your answer. It seems to be working but I've only get one point of the two I should be getting.
Bellow I would give more detailed info of where I am getting the parameters. What I need to achive with this code is the width of bell curve created at each cross section of my matrix when y=0.7. After I have this cross section I fit it with a gaussian (which is also not quite working btw) and after that, I try to define the formula given by the fit-Gauss with the parameters and getting the x-values that belong when y=0.7. please help :(
repetitions=300; %Repetitions
x=linspace(0.46,0.7,repeticiones);
correlations=cell2mat(struct2cell(load('Corr2_Matrix_a25_NA022_L8mm_r1010.mat', 'correlaciones'))); %Matrix being used
a=150;cc=150;b=a+cc;
x7=zeros(b+1,1);
for i=a:b
y1=correlaciones(i,:); %cross section at ith row of the matrix
%cut the peak area of the cross section for better fitting with Gaussian fit%
[max_y, max_idx]=max(y1);
x_max=x(max_idx);
interval=0.005; %desired interval before and after the peak
idx=(x_max-interval<x)&(x<x_max+interval);
[x_interval]=x(idx); %values in x around the peak
[y_interval]=y1(idx); %values in y around the peak
figure(1);plot(Gaus_,x_interval,y_interval);
%Fit new peak data to a gaussean%
Gaus_=fit(x_interval.',y_interval.','Gauss2');
Values_=coeffvalues(Gaus_);
a1=Values_(1,1);
b1=Values_(1,2);
c1=Values_(1,3);
a2=Values_(1,4);
b2=Values_(1,5);
c2=Values_(1,6);
y=a1*exp(-((x-b1)/c1).^2)+a1*exp(-((x-b1)/c1).^2);
idx = find(diff(sign(y-0.7)));
for k = 1:numel(idx)
idxrng = [-1 1]+idx(k);
x7(k) = interp1(y(idxrng), x(idxrng), 0.7); % Interpolate To Find Intersection ‘x’-Value
end
end
I get any number of errors when I try to run your code, among which are:
Unrecognized function or variable 'repeticiones'.
and:
Unable to read file 'Corr2_Matrix_a25_NA022_L8mm_r1010.mat'. No such file or directory.
Perhaps with a bit of explanation I can adapt my code to your problem.
Please only provide the necesary vectors. I do not need everything, I only need enough to approximate the curve you want to estimate.
oh yes, sorry. some of my code had spanish words and in the translation to put it here forgot to change some.
if you could please chnage:
x=linspace(0.46,0.7,repetitions);
and
y1=correlations(i,:);
and I don't really know how to share my matrix here(Corr_Matrix_a25_NA022...)
It took me a while to get that to run. (I do not have the Curve Fitting Toolbox — I do not need it for what I do — so I had to adapt that part.)
I do not understand the reason for the curve fits, since they do not even begin to approximate your data in most instances, and therefore produce the wrong intersection calculations and the wrong width results.
With the current indexing, the first 149 entries are all 0. That is inefficient. Change the loop indexing to:
iv=a:b;
for i=1:numel(iv)
...
end
and to get the matrix indexing correct:
y1=correlations(iv(i),:);
I would abandon the curve fits, and I would instead use only the data to get the intersections and widths:
idx = find(diff(sign(y_interval-0.7)));
if (numel(idx) < 2)
wdth(i) = NaN;
continue
end
for k = 1:numel(idx)
idxrng = [-1 1]+idx(k);
x7(i,k) = interp1(y_interval(idxrng), x_interval(idxrng), 0.7, 'linear','extrap'); % Interpolate To Find Intersection ‘x’-Value
end
wdth(i) = x7(i,2) - x7(i,1); % Calculate & Store The Widths
The if block traps a couple instances where the data are not a peak and have fewer than two intersections.
Then after the ‘i’ loop, if you want:
Width_Stats = [nnz(~isnan(wdth)); mean(wdth,'omitnan'); median(wdth,'omitnan'); std(wdth,'omitnan')]
producing:
Width_Stats =
1.480000000000000e+02
3.432059519717543e-03
3.416623985254608e-03
6.019995261981107e-04
so the mean width is 0.00343, and the standard deviation is 0.000602.
Sir/Madam, May God bless you, your family and everything you do! you just saved my bachelor project, It works perfectly. Thank you very much
The reason for the fitting was to connect the data points which I thought necessary to find the x_values at y=0.7. would you care to explain a little bit on how you made this possible without a fitting? again, thanks.
As always, my pleasure!
After about a half hour of experimentation with the fitting (all unsuccessful), I simply used the raw data, and use the if block to trap segments that either did not reach the 0.7 level or that did not have 2 intercepts with it.. The fitting is likely not necessary (or at least a different model would be necessary, since the Gaussian gives a very poor approximation). I do not know what your data are, however if you want to fit them (although I do not recommend that), a sinc function of some sort (with more parameters, for example amplitude, position, and width) could be more appropriate than the Gaussian.
(For the record, I am male.)

Sign in to comment.

More Answers (2)

You can take your curve as L1 and define your straight line at y = 0.7 as curve L1 and use InterX. Get the function InterX from:
With your particular function you can get both values of x immediately from
x = b1 + c1*sqrt(log(a1/0.7))*[1, -1];

1 Comment

Hi, thanks for your answer! It really seems to work for the formula I gave above which corresponce to a Gauss1 fit. But as it happens it is not fitting my data anymore and I'm using Gauss2 now:
y=a1*exp(-((x-b1)/c1).^2)+a1*exp(-((x-b1)/c1).^2)
and with this one the method you gave is not working :(

Sign in to comment.

Categories

Community Treasure Hunt

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

Start Hunting!