[elec,sels, electrodes] = ng_tank_find_elec(srf,vtx,fc,centres); This function Tries to find the electrdes given the x y x coords of their centres. Version 5.0 B.D.Grieve - 13/02/2002 + modyfication by lmazurk WRBL added default as prevous choice 20/1/2004 WRBL deleted ground plane 05/12/2005 WRBL derived automatic version ditto AA speedup and fix to not output zeros AA add ability to define electrodes with a function srf = The boundary surfaces vtx = The vertices matrix fc = A one column matrix containing the face numbers elsrf = Cell array of indices matrices mapping into vtx each electrode face sels = The indices into the srf matrix of the selected electrode faces elec = The EIDORS-3D electrode matrix of dimensions NxM, where where N: no. of electrodes, M: 3 * max no. of faces per electrode [ kept for backward compatibility. Use electrodes output instead] centres(k,:)=[ x,y,z ] of kth electrode OR centres = struct where centres(k).centre is electrode centre and centres(k).fcn = fcn of vtx and ctr which is zero outside and one inside electrode example: ctr_fcn = inline( 'sum((vtx-ones(size(vtx,1),1)*ctr).^2,2)<1', ... 'vtx','ctr'); [ctr_param(1:nn).fcn] = deal( ctr_fcn ); centres= mat2cell( [x(:),y(:),z(:)], ones(nn,1),3); [ctr_param(1:nn).centre] = deal( centres{:} ); this form allows for more complicated electrode shapes electrodes = EIDORS V3.x electrodes structure
0001 function [elec,sels, electrodes] = ng_tank_find_elec(srf,vtx,fc,centres) 0002 %[elec,sels, electrodes] = ng_tank_find_elec(srf,vtx,fc,centres); 0003 % 0004 % This function Tries to find the electrdes given the x y x coords of their centres. 0005 % 0006 % Version 5.0 0007 % B.D.Grieve - 13/02/2002 + modyfication by lmazurk 0008 % WRBL added default as prevous choice 20/1/2004 0009 % WRBL deleted ground plane 05/12/2005 0010 % WRBL derived automatic version ditto 0011 % AA speedup and fix to not output zeros 0012 % AA add ability to define electrodes with a function 0013 % 0014 % srf = The boundary surfaces 0015 % vtx = The vertices matrix 0016 % fc = A one column matrix containing the face numbers 0017 % elsrf = Cell array of indices matrices mapping into vtx each electrode face 0018 % sels = The indices into the srf matrix of the selected electrode faces 0019 % elec = The EIDORS-3D electrode matrix of dimensions NxM, where 0020 % where N: no. of electrodes, M: 3 * max no. of faces per electrode 0021 % [ kept for backward compatibility. Use electrodes output instead] 0022 % centres(k,:)=[ x,y,z ] of kth electrode 0023 % OR 0024 % centres = struct where centres(k).centre is electrode centre and 0025 % centres(k).fcn = fcn of vtx and ctr which is 0026 % zero outside and one inside electrode 0027 % example: ctr_fcn = inline( 'sum((vtx-ones(size(vtx,1),1)*ctr).^2,2)<1', ... 0028 % 'vtx','ctr'); 0029 % [ctr_param(1:nn).fcn] = deal( ctr_fcn ); 0030 % centres= mat2cell( [x(:),y(:),z(:)], ones(nn,1),3); 0031 % [ctr_param(1:nn).centre] = deal( centres{:} ); 0032 % this form allows for more complicated electrode shapes 0033 % 0034 % electrodes = EIDORS V3.x electrodes structure 0035 0036 % WARNING! the 'fc' variable in this function is what everywhere else is 0037 % called 'bc', and that's how it should be used. 0038 0039 % (C) 2002-2006. Licenced under the GPL 0040 % $Id: ng_tank_find_elec.m 6045 2019-12-31 20:09:02Z aadler $ 0041 0042 if isstruct(centres) 0043 % Calc centre of each surface 0044 for d=1:size(vtx,2) 0045 srfctr(:,d) = mean(reshape( vtx(srf,d), size(srf) ),2); 0046 end 0047 for e=1:length(centres) 0048 inside = feval(centres(e).fcn,srfctr,centres(e).centre); 0049 this_el = srf(inside,:); 0050 electrodes(e).nodes = unique( this_el(:) )'; 0051 electrodes(e).z_contact = 0.1; % set placeholder value 0052 end 0053 elec= NaN; sels= NaN; % No backward compatible for this mode 0054 elseif size(centres,2)==3; 0055 [elec,sels, electrodes] = find_elec_centres(srf,vtx,fc,centres); 0056 else 0057 error('don`t understand format of centres'); 0058 end 0059 0060 0061 function [elec,sels, electrodes] = find_elec_centres(srf,vtx,fc,centres); 0062 0063 for loop1 = 1:max(fc) 0064 % Create a logical array (lgelfc) to determine which faces are electrodes 0065 lgelfc(loop1) = logical(0); 0066 0067 % [fcsrf,fci] = ng_extract_face(srf,vtx,fc,loop1); 0068 fci = find( fc == loop1 ); 0069 fcsrf= srf(fci,:); % should be vertex numbers for this face 0070 fcsrf= unique(fcsrf); fcsrf= fcsrf(fcsrf>0); 0071 coordsforthisface= vtx(fcsrf,:); 0072 face_coords{loop1}= coordsforthisface; 0073 ttlfcsrf(loop1) = {fcsrf}; 0074 0075 end 0076 0077 0078 [sels,lgelfc] = find_selected_face(centres, face_coords, lgelfc); 0079 0080 0081 0082 % Extract from the total face indices matrix (ttlfcsrf) the 0083 % faces which are electrodes and store them in the cell 0084 % array (elsrf) 0085 elsrf = ttlfcsrf(lgelfc); 0086 0087 if 0 0088 % Display each electrode in turn as a wire mesh 0089 figure 0090 set(gcf,'Name','Wire Mesh Electrode Faces') 0091 for loop1 = 1:size(elsrf,2) 0092 trimesh(elsrf{loop1},vtx(:,1),vtx(:,2),vtx(:,3),'EdgeColor','red') 0093 title(['Electrode ' num2str(loop1) ': red']) 0094 axis equal 0095 axis(mshaxs) 0096 view(45,10) 0097 hidden off 0098 hold on 0099 pause(0.75) 0100 end 0101 title('Electrodes: red,') 0102 hidden off 0103 pause(2) 0104 end 0105 % Convert elsrf into the EIDORS-3D matrix electrode matrix format 0106 0107 nmel = size(elsrf,2); 0108 for loop1 = 1:nmel 0109 nmfc(loop1) = size(elsrf{loop1},1); 0110 end 0111 % Initiate electrode matrix (elec) & pad with zeros 0112 elec = zeros(nmel,3*max(nmfc)); 0113 % Put electrode surface information into elec 0114 for loop1 = 1:nmel 0115 el_idx= sels(loop1); 0116 this_el= ttlfcsrf{el_idx}'; 0117 l_this_el= prod(size(this_el)); 0118 elec(loop1, 1:l_this_el) = this_el(:)'; 0119 0120 electrodes(loop1).nodes = unique( this_el(:) )'; 0121 electrodes(loop1).z_contact = 0.1; % set placeholder value 0122 end 0123 0124 0125 % Find the electrode node which is closest to the specified point 0126 function [sels,lgelfc] = find_selected_face(centres, face_coords, lgelfc) 0127 sels = []; 0128 elecn_idx= []; 0129 elecnodes= []; 0130 for i=1:length(face_coords) 0131 elecn_idx = [elecn_idx; i*ones(length(face_coords{i}),1)]; 0132 elecnodes = [elecnodes; face_coords{i}]; 0133 end 0134 elecsep = sum(min(abs(diff(centres)))); 0135 for ielec = 1:size(centres,1) 0136 % Find the distance from the centre of faces to this electrode 0137 dists = (elecnodes(:,1) - centres(ielec,1)).^2 + ... 0138 (elecnodes(:,2) - centres(ielec,2)).^2 + ... 0139 (elecnodes(:,3) - centres(ielec,3)).^2; 0140 dmin = min(dists); %iface is closest face to this electrode. 0141 % take the first, closest ones 0142 iface = find(dmin + elecsep >= dists); 0143 if length(iface)>1 % found electrode and background. Take smallest 0144 tryfaces = unique( elecn_idx(iface)); 0145 ff=[]; for i=1:length(tryfaces) 0146 ff(i) = max( dists( elecn_idx == tryfaces(i))); 0147 end 0148 [~, i] = min(ff); 0149 iface = tryfaces(i); 0150 else 0151 iface = elecn_idx(iface); 0152 end 0153 lgelfc(iface) = true; 0154 if sum(lgelfc) ~= ielec 0155 % disp(ielec); 0156 error('Electrode #%d not found', ielec); 0157 end 0158 sels(ielec)= iface; 0159 % disp([ielec, iface, d]); 0160 % now remove that face so we dont use it again 0161 ff = find(elecn_idx == iface); 0162 elecn_idx(ff,:) = []; 0163 elecnodes(ff,:) = []; 0164 end 0165 0166 function [sels,lgelfc] = find_selected_face_old(centres, face_coords, lgelfc) 0167 sels = []; 0168 for i=1:length(face_coords) 0169 centreofface(i,:)= mean(face_coords{i}); 0170 end 0171 for ielec = 1:size(centres,1) 0172 % Find the distance from the centre of faces to this electrode 0173 dists = (centreofface(:,1) - centres(ielec,1)).^2 + ... 0174 (centreofface(:,2) - centres(ielec,2)).^2 + ... 0175 (centreofface(:,3) - centres(ielec,3)).^2; 0176 [d,iface] = min(dists); %iface is closest face to this electrode. 0177 lgelfc(iface) = logical(1); 0178 if sum(lgelfc) ~= ielec 0179 disp(ielec); 0180 error('Electrode #%d not found', ielec); 0181 end 0182 sels(ielec)= iface; 0183 % disp([ielec, iface, d]); 0184 end