30 views (last 30 days)
NA on 31 Jan 2019
Edited: Jan on 6 Feb 2019
I have A={[1,2,4],[2,3,4],[2,4,5],[4,5,6,9,10,11],[4,7,9],[7,8],[6,12,13]} and ref={[1],[1],[1],[3],[2],[1]} (ref means that which index in A is chosen as reference). So according to each referance ang is calculated in each array. ang={[0; -0.08;-0.17],[0;-0.14;0.09],[0;-0.09;-0.05],[0.05; 0.09; 0; -0.02;-0.03;-0.03],[0;-0.02;-0.01],[0.004;0],[0;-0.02;-0.01]}
[0; -0.08;-0.17] means that first elemnt is chosen as referance so -0.08 is calculated according to 1 as reference.
As I want to change all referance according to 1.
[1,2,4]=[0; -0.08;-0.17] this one is not changing
[2,3,4] as 2 is reference here so I need scale up all element to -0.08 (add all element to -0.08)
[2,3,4]=[0+(-0.08);-0.14+(-0.08);-0.09+(-0.08)] =[-0.08;-0.22;-0.17]
for [2,4,5] as reference is not changing only need to add all to -0.08
[2,4,5]=[0;-0.09+(-0.08);-0.05+(-0.08)]=[0;-0.17;-0.13]
for [4,5,6,9,10,11] as 6 is reference, I need to scale up. we know that ang(4)should be-0.17 and ang(4) here is 0.05. need to change 0.05 to -0.17 .
(0.05+(X)=-0.17, X=-0.22) need to add all to -0.22
[4,5,6,9,10,11]=[0.05+(X); 0.09-0.22; 0+(-0.22); -0.02+(-0.22);-0.03+(-0.22);-0.03+(-0.22)] =[-0.17;-0.13;-0.22; -0.24;-0.25;-0.25]
for [4,7,9] ang(4) should be -0.17. so add all to -0.17
[4,7,9]=[0+(-0.17);-0.02+(-0.17);-0.01+(-0.17)]=[-0.17;-0.19;-0.18]
for [7,8] from the above we know ang(7) should be -0.19 so add all to -0.19
[7,8]=[0.004+(X);0+(-0.186)]=[-0.19;-0.186] 0.004+(X)=-0.19 X=-0.186
[6,12,13]=[0+(-0.22);-0.02+(-0.22);-0.01+(-0.22)]
result should be [1,2,3,4,5,6,7,8,9,10,11,12,13]=[0,-0.08,-0.22;-0.17;-0.13;-0.22;-0.19;-0.186; -0.18;-0.25;-0.25]]
I also try this
tmp = cellfun(@(c,p,m)c+c(p(m)),ang,A,ref,'uni',0);
but it is not working

NA on 1 Feb 2019
A={[1,2,4],[2,3,4],[2,4,5],[4,5,6,9,10,11],[4,7,9],[7,8],[6,12,13]};
ref={[1],[1],[1],[3],[1],[2],[1]} ;
ang={[0; -0.08;-0.17],[0;-0.14;0.09],[0;-0.09;-0.05],[0.05; 0.09; 0; -0.02;-0.03;-0.03],[0;-0.02;-0.01],[0.004;0],[0;-0.02;-0.01]};
tmp = cellfun(@(c,p,m)c+c(p(m)),ang,A,ref,'uni',0);
idx = [A{:}];
correct = zeros(1,max(idx));
correct(idx) = vertcat(tmp{:}); % Vertically concatenate tmp{1}, tmp{2}, ...
correct=correct';
I change ref and tmp, according to explanation
tmp = cellfun(@(c,p,m)c+c(p(m)),ang,A,ref,'uni',0);
By this I have error
Jan on 1 Feb 2019
@Naime: Whenever you mention in the forum, that you get an error, post a copy of the complete error message. Provide all information, which is required to help you.
NA on 1 Feb 2019
but I really don't get the "I need scale up all element to -0.08 (add all element to -0.08)". Where does that -0.08 come from?
I mean for this array [2,3,4], I need to add all ang [0;-0.14;0.09] to -0.08.
As in the first one [1,2,4]=[0; -0.08;-0.17] ang(2) is -0.08.
So, if I want to compare all ang I need to chage reference. as reference is different in each array of A.
Same for ''we know that ang(4)should be-0.17''Do we? Why?
After adding -0.08 to [0;-0.14;0.09] I have [-0.08;-0.22;-0.17]. so [-0.08;-0.22;-0.17] correspond to [2,3,4]. ang(4)=-0.17

Jan on 6 Feb 2019
Edited: Jan on 6 Feb 2019
I haven't seen a demand for such an indirekt algorithm yet, but if this really satisfies your needs, there is no reason to change the code. With the above mentioned simplifications:
A = {[1,2,4],[2,3,4],[2,4,5],[4,5,6,9,10,11],[4,7,9],[7,8],[6,12,13]};
ref = {[1],[1],[1],[3],[1],[2],[1]};
ang = {[0; -0.08;-0.17],[0;-0.14;-0.09],[0;-0.09;-0.05],[0.05; 0.09; 0; -0.02;-0.03;-0.03],[0;-0.02;-0.07],[0.004;0],[0;-0.02;-0.01]};
new_ang = zeros(1, max([A{:}]));
for k = 1:numel(A)
index = A{k};
first = index(1);
if ang{k}(1) == 0
% if any(A{k} == 1)
% new_ang(index) = new_ang(first) + ang{k};
% elseif any(A{k} == first)
% new_ang(index) = new_ang(first) + ang{k};
% end
% Because both assigments are equal, this is more elegant:
if any(A{k} == 1) || any(A{k} == first)
new_ang(index) = new_ang(first) + ang{k};
end
else
new_ang(index) = new_ang(first) - ang{k}(1) + ang{k};
end
end
Or
new_ang = zeros(1, max([A{:}]));
for k = 1:numel(A)
index = A{k};
first = index(1);
if ang{k}(1) ~= 0 || (any(A{k} == 1) || any(A{k} == first))
new_ang(index) = new_ang(first) - ang{k}(1) + ang{k};
end
end

Jan on 1 Feb 2019
I strongly recommend to avoid the smart and neat cellfun, if its compact notation confuses the programmer. A simple loop might look less professional, but it can save hours for debugging.
tmp = cell(size(ang));
for k = 1:numel(A)
tmp{k} = ang{k} + ang{A{ref{k}}};
end
In your cellfun approach, A is treated as 2nd input, such that the anoynmous function
@(c,p,m)c+c(p(m))
defines p=A{k}, but this is not wanted. I assume you want:
tmp = cellfun(@(c,m) c+c(A(m)), ang, ref, 'uni', 0);
Anonymous functions cannot be debugged directly, but the suggested loop can. So do not make the programming harder than needed.

NA on 4 Feb 2019
the variable A is used only to determine the size, but the elements are not used.
in this system I have a 13 measurements (1 to 13) and measuremnts is grouped according to A={[1,2,4],[2,3,4],[2,4,5],[4,5,6,9,10,11],[4,7,9],[7,8],[6,12,13]};
So, A is important as illustrate which measurement has which value (ang).
ang={[0; -0.08;-0.17],[0;-0.14;-0.09],[0;-0.09;-0.05],[0.05; 0.09; 0; -0.02;-0.03;-0.03],[0;-0.02;-0.07],[0.004;0],[0;-0.02;-0.01]};
In each group base measuremnet (measurement that is zero) is different. As I want to compare all 13 measurements, I need to have one base and other values changing according to this base (measurement 1)
this base measurement is understandable according to ref={[1],[1],[1],[3],[1],[2],[1]} ;
Correct one
[7,8]=[0.004+(X);0+(-0.194)]=[-0.19;-0.194]
0.004+(X)=-0.19 X=-0.194
As measurement 8 is located only in one group [7,8], I could not compare value of this measurement according to other. But 7 is in group [4,7,9] and calculate ang(7) = -0.02-0.17=-0.19 , ang (7) should be -0.19 in all groups
[7,8] without changing to one base is [0.004;0]. if I change to one base ang(7) = -0.19
for this reason 0.004 should be change to -0.19 so, need to add 0.004 to -0.194 to get -0.19.
So ang(8) become-0.194
NA on 5 Feb 2019
A={[1,2,4],[2,3,4],[2,4,5],[4,5,6,9,10,11],[4,7,9],[7,8],[6,12,13]};
ref={[1],[1],[1],[3],[1],[2],[1]};
ang={[0; -0.08;-0.17],[0;-0.14;-0.09],[0;-0.09;-0.05],[0.05; 0.09; 0; -0.02;-0.03;-0.03],[0;-0.02;-0.07],[0.004;0],[0;-0.02;-0.01]};
idx = [A{:}];
new_ang = zeros(1,max(idx));
for k = 1:numel(A)
index=A{k};
first_element=index(1);
if ang{k}(1)==0
if any(ismember(A{k},1))==1
new_ang(index)=new_ang(first_element)+ang{k};
else
n=find(new_ang~=0);
if any(ismember(A{k},first_element))==1
new_ang(index)=new_ang(first_element)+ang{k};
end
end
else
X=new_ang(first_element)-ang{k}(1);
new_ang(index)=X+ang{k};
end
end
This one gives me correct result
But is there any short version for this?
Jan on 6 Feb 2019
The result of n=find(new_ang~=0) is not used anywhere, so simply omit it. You can abbreviate:
if any(ismember(A{k},first_element))==1
to
if any(A{k} == first_element)