Calculating and printing uncertainties of fits after the "normal" display of fit-parameters

4 views (last 30 days)
Hello,
I am storing multiple fits in a cell array "fits". Currently I am just using celldisp to obtain f.e. the following:
>> celldisp(fit)
fit{1} =
Linear model Poly1:
y(x) = p1*x + p2
Coefficients (with 95% confidence bounds):
p1 = 0.00226 (0.002015, 0.002506)
p2 = 0.004049 (0.003472, 0.004627)
fit{2} =
Linear model Poly1:
y(x) = p1*x + p2
Coefficients (with 95% confidence bounds):
p1 = 0.004422 (0.004302, 0.004542)
p2 = 0.003982 (0.0037, 0.004264)
Now I am trying to print the following instead to the command window:
Fit{1} = % What I would like to print instead
Linear model Poly1:
y(x) = p1*x + p2
Coefficients (with 95% confidence bounds):
p1 = 0.00226 (0.002015, 0.002506) +- 0.000246 % (values obtained by calculating upper bound - value outside brackets)
p2 = 0.004049 (0.003472, 0.004627) +- 0.000578 % (i.e 0.004627-0.004049=0.000578 and so on)
Fit{2} =
Linear model Poly1:
y(x) = p1*x + p2
Coefficients (with 95% confidence bounds):
p1 = 0.004422 (0.004302, 0.004542) +- 0.00012
p2 = 0.003982 (0.0037, 0.004264) +- 0.000282
My first idea was to then extract the values from the different fits:
for j=1:1:numel(fit)
% Extract All Data:
Coeffvalues{j}=coeffvalues(fit{j}); % get the p1 and p2 values
Confintvalues{j}=confint(fit{j}); % get the corresponding confidence bounds
end
for j=1:1:numel(Coeffvalues)
Confintcalcvals=Confintvalues{j}(2,:)';
for k=1:1:length(Coeffvalues{1,1})
Difference(j,k)= Confintcalcvals(k)-Coeffvalues{1,j}(k); % Row j contains the diffs for fit j, position k is for the respective value
end
end
Difference % contains the differences to be inserted into the displayed fit messages, one row per fit
Now I should have all data I need in nice sorted columns, one per parameter.
My problem now is that I have no clue whatsoever how to emulate the message given when fits are displayed, and then add these values at the correct positions. For instance, I couldn't figure out how to access the string of the cfit-object containing the fit equation, since I assume I would have to rebuild the entire message string by string, which I only now realise could become a pain in the ass if we have a differing number of Coefficients. No clue how to do that automatically aside from coding it for the first X possibilities and just hope you won't encounter a fit with more than X parameters. I assume this is not the best way.
This gets worse since I have to make the entire process loopable so it repeats for whatever number of fits I end up having.
Thank you & stay save.
C.A.

Accepted Answer

Uday Pradhan
Uday Pradhan on 6 Sep 2020
Hi Claudius,
I would suggest to create a custom display function for this task. I have created a function that I describe below. You may refer and use this or create your own if this gives you a better and/or efficient idea.
function celldispForFits(someCell) %someCell is the cell of fits
s = inputname(1);
for i = 1:numel(someCell)
modelDetails=evalc('disp(someCell{i})'); %get the display message as a char array
strMessage = editMessage(modelDetails,someCell{i}); %get the updated message
fprintf('\n');
disp([s subs(i,size(someCell)) ' =']) %taken this from the original celldisp function
fprintf('\n');
disp(strMessage);
end
function s = subs(i,siz)
%SUBS Display subscripts
if length(siz)==2 && any(any(siz==1))
v = cell(1,1);
else
v = cell(size(siz));
end
[v{1:end}] = ind2sub(siz,i);
s = ['{' int2str(v{1})];
for i=2:length(v)
s = [s ',' int2str(v{i})];
end
s = [s '}'];
end
end
In a separate file, I created the function "editMessage" which edits the original message and applies the changes that you have mentioned in your question.
function s = editMessage(modelDetails,f) %f = fit Object, modelDetails the original displayed message
displayStr = split(modelDetails,newline); %split the message with respect to newline delimiter
displayStr = displayStr(~cellfun('isempty',displayStr)); %remove the empty arrays that may occur
var = 4; %line number in the message from which editing is required
for i = 1 : numel(displayStr) %loop through each line in the message
k = 1;
while displayStr{i}(k) == ' '
k = k + 1; %for each line search for the first word
end
str = "";
while displayStr{i}(k) ~= ' '
str = str + displayStr{i}(k);
k = k + 1; %get the first word in the line
end
if str == "Coefficients"
var = i + 1; %if the word is Coefficients store the next line number
break; %this is the line number from which we need to start editing the message
end
end
coeffVals = coeffvalues(f);
confidenceInt = confint(f);
toAdd = [""]; %new edits to be inserted
for i = 1:numel(coeffVals)
toAdd(i) = num2str(confidenceInt(2,i) - coeffVals(i));
%upper bound - value
end
idx = 1;
for i = var : numel(displayStr) %from the line number in var till the end
displayStr{i} = displayStr{i} + " +- " + toAdd(idx); %make the required edits
idx = idx + 1;
end
finalStr = "";
for i = 1:numel(displayStr)
finalStr = finalStr + displayStr(i) + newline; %create the new message to display
end
s = finalStr;
end
These functions make the assumption that the lines that need editing occur after the line "Coefficients (with ...) :" and are not context - aware. I have tested these on some fits that I created and seems to work well on those examples. Hope this will help you.
  3 Comments

Sign in to comment.

More Answers (0)

Products


Release

R2020a

Community Treasure Hunt

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

Start Hunting!