Lsqcurvefit - problem with matrix input

Hi everyone,
I'm trying to use lsqcurvefit to optimize one set of data to look as close as another set.
For this purpose I try to optimize the difference between a fixed vector empty(:,2) and another vector, which I know can be quite nicely tuned using the function (var(:,1) - x(1).*var(:,2) + x(2)). So, the Ydata is obviously a matrix and even though I saw examples of functions being fitted using lsqcurvefit with matrices and also the manual says it's possible, I still get an error. The sizes and dimensions of all inputs are correct, so it can't be the problem.
Here's my code:
%Uploading data from other sources:
var(:,1) = abs_full;
var(:,2) = absorbance_molecule;
%Defining the optim. function + fitting
myfun = @(x,var) empty(:,2) - (var(:,1) - x(1).*var(:,2) + x(2));
x0 = [0.53,0.1];
x = lsqcurvefit(mufyn,x0,wav_full,var);
Here's the error:
Index in position 2 exceeds array bounds. Index must not exceed 1.
Error in kinetics_UV_shifting_background>@(x,var)empty(:,2)-(var(:,1)-x(1).*var(:,2)+x(2)) (line 290)
myfun = @(x,var) empty(:,2) - (var(:,1) - x(1).*var(:,2) + x(2));
Error in lsqcurvefit (line 225)
initVals.F = feval(funfcn_x_xdata{3},xCurrent,XDATA,varargin{:});
Error in kinetics_UV_shifting_background (line 293)
x = lsqcurvefit(myfun,x0,wav_full,var);
Caused by:
Failure in initial objective function evaluation. LSQCURVEFIT cannot continue.
I would be grateful for any help!

Answers (1)

Index in position 2 exceeds array bounds. Index must not exceed 1.
Check to see how many columns ‘empty’ has. It may only have one.

7 Comments

I tried to reduce this two-column vector to only one column (the one I need), but I get the same error.
When I change the function so that it uses only one column of the var variable (for example only var(:,2)) it works without error. But of course I need both to do anything useful. So it would seem the problem comes from using a matrix as input, even though it should be fine for lsqcurvefit.
Having all the data and all the necessary code to work with would definitely help.
EDIT — (9 Jul 2023 at 13:44)
You are creating the ‘var’ matrix, so I doubt that it is the problem. The problem appears to be the ‘empty’ variable, since it appears to have only one column. That throws the error.
.
The rest of the code has 200 lines, but I will just show the essential parts and I highlighted the parts where the code has an issue:
I include the rest of the related code (still not everything, the rest is irrelevant), and I highlight the most essential part that has an issue somewhere.
prompt = {'Wavelength used for kinetics'};
dlgtitle = 'Select wavelength [nm]';
dims = [1 50];
answer = inputdlg(prompt,dlgtitle,dims);
obs_wav = str2double(answer{1});
file_cavity_bg = dlmread('CM-CC-024D cavoffNoOH100eqlutidine20%ACN_RawData-070.txt','');
wavelength = file_cavity_bg(:,1);
files = dir('*.txt');
file_number = 0;
for i=1:length(files)
if length(files(i).name()) > 35;
file_number = file_number + 1;
end
end
min_lim = 610;
max_lim = 636;
initial_spectrum=readmatrix(files(1).name());
wav_initial = initial_spectrum(:,1);
absorbance_initial = initial_spectrum(:,2);
molecule = dlmread('molecule.txt','');
wav_molecule = molecule(:,1);
absorbance_molecule = molecule(:,2);
final = dlmread('final.txt','');
empty = final(:,2);
for i=1:file_number
spectra=readmatrix(files(i).name());
wav = spectra(:,1);
abs = spectra(:,2);
wav_full = spectra(:,1);
abs_full = spectra(:,2);
var(:,1) = abs_full;
var(:,2) = absorbance_molecule;
belowrange = (wav < min_lim);
aboverange = (wav > max_lim);
remove = or(belowrange,aboverange);
wav(remove) = [];
abs(remove) = [];
[~,idx] = max(abs);
maximum(i,1) = wav(idx,1);
myfun = @(x,var) empty(:,1) - (var(:,1) - x(1).*var(:,2) + x(2));
x0 = [0.53,0.1];
x = lsqcurvefit(myfun,x0,wav_full,var);
tmp_bg = abs_full - param(1,1)*absorbance_molecule+param(1,2);
%Find current maximum and phase shift
phase_diff = maximum - max_bg;
abs_bg_shift = zeros(length(abs_full));
if phase_diff > 0
abs_bg_shift = circshift(test,phase_diff);
%abs_bg_shift(phase_diff:end) = abs_bg(length(abs_full));
abs_final = abs_full - abs_bg_shift - tmp_bg;
else
abs_final = abs_full - tmp_bg;
end
a = nlinfit(x,y,@(a0, x) myfun(a0, constants),a0);
idx_kin = find(wav_full == obs_wav);
absorbance_phase_bg(i,1) = abs_final(idx_kin,1);
plot(wav_full,abs_final)
end
You define ‘empty’ here:
empty = final(:,2);
so it only has one column (as I suspected).
Just use:
myfun = @(x,var) empty - (var(:,1) - x(1).*var(:,2) + x(2));
instead, without the subscript reference to ‘empty’, although this:
myfun = @(x,var) empty(:,1) - (var(:,1) - x(1).*var(:,2) + x(2));
should also work.
I would replace the dlmread calls with readmatrix however without the data and the rest of the code, I cannot determine what any remaining problems are, if any remain, or obviously how to fix them.
Thank you for all the help, it still did not work but I found a workaround.
What was the workaround?

Sign in to comment.

Categories

Asked:

on 8 Jul 2023

Commented:

on 10 Jul 2023

Community Treasure Hunt

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

Start Hunting!