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

4 views (last 30 days)
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
for j=1:1:numel(Coeffvalues)
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
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.

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
disp([s subs(i,size(someCell)) ' =']) %taken this from the original celldisp function
function s = subs(i,siz)
%SUBS Display subscripts
if length(siz)==2 && any(any(siz==1))
v = cell(1,1);
v = cell(size(siz));
[v{1:end}] = ind2sub(siz,i);
s = ['{' int2str(v{1})];
for i=2:length(v)
s = [s ',' int2str(v{i})];
s = [s '}'];
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
str = "";
while displayStr{i}(k) ~= ' '
str = str + displayStr{i}(k);
k = k + 1; %get the first word in the line
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
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
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;
finalStr = "";
for i = 1:numel(displayStr)
finalStr = finalStr + displayStr(i) + newline; %create the new message to display
s = finalStr;
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.

Sign in to comment.

More Answers (0)




Community Treasure Hunt

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

Start Hunting!