PageRenderTime 38ms CodeModel.GetById 28ms RepoModel.GetById 0ms app.codeStats 1ms

/plotting/private/warp_apply.m

http://fieldtrip.googlecode.com/
MATLAB | 191 lines | 106 code | 12 blank | 73 comment | 20 complexity | 04cf650ef591ba9cd32c214d6be4bd76 MD5 | raw file
Possible License(s): GPL-2.0, GPL-3.0, AGPL-1.0, BSD-3-Clause, LGPL-2.0, BSD-2-Clause, LGPL-3.0
  1. function [warped] = warp_apply(M, input, method, tol)
  2. % WARP_APPLY performs a 3D linear or nonlinear transformation on the input
  3. % coordinates, similar to those in AIR 3.08. You can find technical
  4. % documentation on warping in general at http://bishopw.loni.ucla.edu/AIR3
  5. %
  6. % Use as
  7. % [warped] = warp_apply(M, input, method, tol)
  8. % where
  9. % M vector or matrix with warping parameters
  10. % input Nx3 matrix with coordinates
  11. % warped Nx3 matrix with coordinates
  12. % method string describing the warping method
  13. % tol (optional) value determining the numerical precision of the
  14. % output, to deal with numerical round off imprecisions due to
  15. % the warping
  16. %
  17. % The methods 'nonlin0', 'nonlin2' ... 'nonlin5' specify a
  18. % polynomial transformation. The size of the transformation matrix
  19. % depends on the order of the warp
  20. % zeroth order : 1 parameter per coordinate (translation)
  21. % first order : 4 parameters per coordinate (total 12, affine)
  22. % second order : 10 parameters per coordinate
  23. % third order : 20 parameters per coordinate
  24. % fourth order : 35 parameters per coordinate
  25. % fifth order : 56 parameters per coordinate (total 168)
  26. % The size of M should be 3xP, where P is the number of parameters
  27. % per coordinate. Alternatively, you can specify the method to be
  28. % 'nonlinear', where the order will be determined from teh size of
  29. % the matrix M.
  30. %
  31. % If the method 'homogeneous' is selected, the input matrix M should be
  32. % a 4x4 homogenous transformation matrix.
  33. %
  34. % If any other method is selected, it is assumed that it specifies
  35. % the name of an auxiliary function that will, when given the input
  36. % parameter vector M, return an 4x4 homogenous transformation
  37. % matrix. Supplied functions in teh warping toolbox are translate,
  38. % rotate, scale, rigidbody, globalrescale, traditional, affine,
  39. % perspective.
  40. % Copyright (C) 2000-2005, Robert Oostenveld
  41. %
  42. % This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip
  43. % for the documentation and details.
  44. %
  45. % FieldTrip is free software: you can redistribute it and/or modify
  46. % it under the terms of the GNU General Public License as published by
  47. % the Free Software Foundation, either version 3 of the License, or
  48. % (at your option) any later version.
  49. %
  50. % FieldTrip is distributed in the hope that it will be useful,
  51. % but WITHOUT ANY WARRANTY; without even the implied warranty of
  52. % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  53. % GNU General Public License for more details.
  54. %
  55. % You should have received a copy of the GNU General Public License
  56. % along with FieldTrip. If not, see <http://www.gnu.org/licenses/>.
  57. %
  58. % $Id: warp_apply.m 5668 2012-04-19 13:56:53Z jansch $
  59. if nargin<4
  60. tol = [];
  61. end
  62. if nargin<3 && all(size(M)==4)
  63. % no specific transformation mode has been selected
  64. % it looks like a homogenous transformation matrix
  65. method = 'homogeneous';
  66. elseif nargin<3
  67. % the default method is 'nonlinear'
  68. method = 'nonlinear';
  69. end
  70. if size(input,2)==2
  71. % convert the input points from 2D to 3D representation
  72. input(:,3) = 0;
  73. input3d = false;
  74. else
  75. input3d = true;
  76. end
  77. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  78. % nonlinear warping
  79. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  80. if any(strcmp(method, {'nonlinear', 'nonlin0', 'nonlin1', 'nonlin2', 'nonlin3', 'nonlin4', 'nonlin5'}))
  81. x = input(:,1);
  82. y = input(:,2);
  83. z = input(:,3);
  84. s = size(M);
  85. if s(1)~=3
  86. error('invalid size of nonlinear transformation matrix');
  87. elseif strcmp(method, 'nonlin0') && s(2)~=1
  88. error('invalid size of nonlinear transformation matrix');
  89. elseif strcmp(method, 'nonlin1') && s(2)~=4
  90. error('invalid size of nonlinear transformation matrix');
  91. elseif strcmp(method, 'nonlin2') && s(2)~=10
  92. error('invalid size of nonlinear transformation matrix');
  93. elseif strcmp(method, 'nonlin3') && s(2)~=20
  94. error('invalid size of nonlinear transformation matrix');
  95. elseif strcmp(method, 'nonlin4') && s(2)~=35
  96. error('invalid size of nonlinear transformation matrix');
  97. elseif strcmp(method, 'nonlin5') && s(2)~=56
  98. error('invalid size of nonlinear transformation matrix');
  99. end
  100. if s(2)==1
  101. % this is a translation, which in a strict sense is not the 0th order nonlinear transformation
  102. xx = M(1,1) + x;
  103. yy = M(2,1) + y;
  104. zz = M(3,1) + z;
  105. elseif s(2)==4
  106. xx = M(1,1) + M(1,2)*x + M(1,3)*y + M(1,4)*z;
  107. yy = M(2,1) + M(2,2)*x + M(2,3)*y + M(2,4)*z;
  108. zz = M(3,1) + M(3,2)*x + M(3,3)*y + M(3,4)*z;
  109. elseif s(2)==10
  110. xx = M(1,1) + M(1,2)*x + M(1,3)*y + M(1,4)*z + M(1,5)*x.*x + M(1,6)*x.*y + M(1,7)*x.*z + M(1,8)*y.*y + M(1,9)*y.*z + M(1,10)*z.*z;
  111. yy = M(2,1) + M(2,2)*x + M(2,3)*y + M(2,4)*z + M(2,5)*x.*x + M(2,6)*x.*y + M(2,7)*x.*z + M(2,8)*y.*y + M(2,9)*y.*z + M(2,10)*z.*z;
  112. zz = M(3,1) + M(3,2)*x + M(3,3)*y + M(3,4)*z + M(3,5)*x.*x + M(3,6)*x.*y + M(3,7)*x.*z + M(3,8)*y.*y + M(3,9)*y.*z + M(3,10)*z.*z;
  113. elseif s(2)==20
  114. xx = M(1,1) + M(1,2)*x + M(1,3)*y + M(1,4)*z + M(1,5)*x.*x + M(1,6)*x.*y + M(1,7)*x.*z + M(1,8)*y.*y + M(1,9)*y.*z + M(1,10)*z.*z + M(1,11)*x.*x.*x + M(1,12)*x.*x.*y + M(1,13)*x.*x.*z + M(1,14)*x.*y.*y + M(1,15)*x.*y.*z + M(1,16)*x.*z.*z + M(1,17)*y.*y.*y + M(1,18)*y.*y.*z + M(1,19)*y.*z.*z + M(1,20)*z.*z.*z;
  115. yy = M(2,1) + M(2,2)*x + M(2,3)*y + M(2,4)*z + M(2,5)*x.*x + M(2,6)*x.*y + M(2,7)*x.*z + M(2,8)*y.*y + M(2,9)*y.*z + M(2,10)*z.*z + M(2,11)*x.*x.*x + M(2,12)*x.*x.*y + M(2,13)*x.*x.*z + M(2,14)*x.*y.*y + M(2,15)*x.*y.*z + M(2,16)*x.*z.*z + M(2,17)*y.*y.*y + M(2,18)*y.*y.*z + M(2,19)*y.*z.*z + M(2,20)*z.*z.*z;
  116. zz = M(3,1) + M(3,2)*x + M(3,3)*y + M(3,4)*z + M(3,5)*x.*x + M(3,6)*x.*y + M(3,7)*x.*z + M(3,8)*y.*y + M(3,9)*y.*z + M(3,10)*z.*z + M(3,11)*x.*x.*x + M(3,12)*x.*x.*y + M(3,13)*x.*x.*z + M(3,14)*x.*y.*y + M(3,15)*x.*y.*z + M(3,16)*x.*z.*z + M(3,17)*y.*y.*y + M(3,18)*y.*y.*z + M(3,19)*y.*z.*z + M(3,20)*z.*z.*z;
  117. elseif s(2)==35
  118. xx = M(1,1) + M(1,2)*x + M(1,3)*y + M(1,4)*z + M(1,5)*x.*x + M(1,6)*x.*y + M(1,7)*x.*z + M(1,8)*y.*y + M(1,9)*y.*z + M(1,10)*z.*z + M(1,11)*x.*x.*x + M(1,12)*x.*x.*y + M(1,13)*x.*x.*z + M(1,14)*x.*y.*y + M(1,15)*x.*y.*z + M(1,16)*x.*z.*z + M(1,17)*y.*y.*y + M(1,18)*y.*y.*z + M(1,19)*y.*z.*z + M(1,20)*z.*z.*z + M(1,21)*x.*x.*x.*x + M(1,22)*x.*x.*x.*y + M(1,23)*x.*x.*x.*z + M(1,24)*x.*x.*y.*y + M(1,25)*x.*x.*y.*z + M(1,26)*x.*x.*z.*z + M(1,27)*x.*y.*y.*y + M(1,28)*x.*y.*y.*z + M(1,29)*x.*y.*z.*z + M(1,30)*x.*z.*z.*z + M(1,31)*y.*y.*y.*y + M(1,32)*y.*y.*y.*z + M(1,33)*y.*y.*z.*z + M(1,34)*y.*z.*z.*z + M(1,35)*z.*z.*z.*z;
  119. yy = M(2,1) + M(2,2)*x + M(2,3)*y + M(2,4)*z + M(2,5)*x.*x + M(2,6)*x.*y + M(2,7)*x.*z + M(2,8)*y.*y + M(2,9)*y.*z + M(2,10)*z.*z + M(2,11)*x.*x.*x + M(2,12)*x.*x.*y + M(2,13)*x.*x.*z + M(2,14)*x.*y.*y + M(2,15)*x.*y.*z + M(2,16)*x.*z.*z + M(2,17)*y.*y.*y + M(2,18)*y.*y.*z + M(2,19)*y.*z.*z + M(2,20)*z.*z.*z + M(2,21)*x.*x.*x.*x + M(2,22)*x.*x.*x.*y + M(2,23)*x.*x.*x.*z + M(2,24)*x.*x.*y.*y + M(2,25)*x.*x.*y.*z + M(2,26)*x.*x.*z.*z + M(2,27)*x.*y.*y.*y + M(2,28)*x.*y.*y.*z + M(2,29)*x.*y.*z.*z + M(2,30)*x.*z.*z.*z + M(2,31)*y.*y.*y.*y + M(2,32)*y.*y.*y.*z + M(2,33)*y.*y.*z.*z + M(2,34)*y.*z.*z.*z + M(2,35)*z.*z.*z.*z;
  120. zz = M(3,1) + M(3,2)*x + M(3,3)*y + M(3,4)*z + M(3,5)*x.*x + M(3,6)*x.*y + M(3,7)*x.*z + M(3,8)*y.*y + M(3,9)*y.*z + M(3,10)*z.*z + M(3,11)*x.*x.*x + M(3,12)*x.*x.*y + M(3,13)*x.*x.*z + M(3,14)*x.*y.*y + M(3,15)*x.*y.*z + M(3,16)*x.*z.*z + M(3,17)*y.*y.*y + M(3,18)*y.*y.*z + M(3,19)*y.*z.*z + M(3,20)*z.*z.*z + M(3,21)*x.*x.*x.*x + M(3,22)*x.*x.*x.*y + M(3,23)*x.*x.*x.*z + M(3,24)*x.*x.*y.*y + M(3,25)*x.*x.*y.*z + M(3,26)*x.*x.*z.*z + M(3,27)*x.*y.*y.*y + M(3,28)*x.*y.*y.*z + M(3,29)*x.*y.*z.*z + M(3,30)*x.*z.*z.*z + M(3,31)*y.*y.*y.*y + M(3,32)*y.*y.*y.*z + M(3,33)*y.*y.*z.*z + M(3,34)*y.*z.*z.*z + M(3,35)*z.*z.*z.*z;
  121. elseif s(2)==56
  122. xx = M(1,1) + M(1,2)*x + M(1,3)*y + M(1,4)*z + M(1,5)*x.*x + M(1,6)*x.*y + M(1,7)*x.*z + M(1,8)*y.*y + M(1,9)*y.*z + M(1,10)*z.*z + M(1,11)*x.*x.*x + M(1,12)*x.*x.*y + M(1,13)*x.*x.*z + M(1,14)*x.*y.*y + M(1,15)*x.*y.*z + M(1,16)*x.*z.*z + M(1,17)*y.*y.*y + M(1,18)*y.*y.*z + M(1,19)*y.*z.*z + M(1,20)*z.*z.*z + M(1,21)*x.*x.*x.*x + M(1,22)*x.*x.*x.*y + M(1,23)*x.*x.*x.*z + M(1,24)*x.*x.*y.*y + M(1,25)*x.*x.*y.*z + M(1,26)*x.*x.*z.*z + M(1,27)*x.*y.*y.*y + M(1,28)*x.*y.*y.*z + M(1,29)*x.*y.*z.*z + M(1,30)*x.*z.*z.*z + M(1,31)*y.*y.*y.*y + M(1,32)*y.*y.*y.*z + M(1,33)*y.*y.*z.*z + M(1,34)*y.*z.*z.*z + M(1,35)*z.*z.*z.*z + M(1,36)*x.*x.*x.*x.*x + M(1,37)*x.*x.*x.*x.*y + M(1,38)*x.*x.*x.*x.*z + M(1,39)*x.*x.*x.*y.*y + M(1,40)*x.*x.*x.*y.*z + M(1,41)*x.*x.*x.*z.*z + M(1,42)*x.*x.*y.*y.*y + M(1,43)*x.*x.*y.*y.*z + M(1,44)*x.*x.*y.*z.*z + M(1,45)*x.*x.*z.*z.*z + M(1,46)*x.*y.*y.*y.*y + M(1,47)*x.*y.*y.*y.*z + M(1,48)*x.*y.*y.*z.*z + M(1,49)*x.*y.*z.*z.*z + M(1,50)*x.*z.*z.*z.*z + M(1,51)*y.*y.*y.*y.*y + M(1,52)*y.*y.*y.*y.*z + M(1,53)*y.*y.*y.*z.*z + M(1,54)*y.*y.*z.*z.*z + M(1,55)*y.*z.*z.*z.*z + M(1,56)*z.*z.*z.*z.*z;
  123. yy = M(2,1) + M(2,2)*x + M(2,3)*y + M(2,4)*z + M(2,5)*x.*x + M(2,6)*x.*y + M(2,7)*x.*z + M(2,8)*y.*y + M(2,9)*y.*z + M(2,10)*z.*z + M(2,11)*x.*x.*x + M(2,12)*x.*x.*y + M(2,13)*x.*x.*z + M(2,14)*x.*y.*y + M(2,15)*x.*y.*z + M(2,16)*x.*z.*z + M(2,17)*y.*y.*y + M(2,18)*y.*y.*z + M(2,19)*y.*z.*z + M(2,20)*z.*z.*z + M(2,21)*x.*x.*x.*x + M(2,22)*x.*x.*x.*y + M(2,23)*x.*x.*x.*z + M(2,24)*x.*x.*y.*y + M(2,25)*x.*x.*y.*z + M(2,26)*x.*x.*z.*z + M(2,27)*x.*y.*y.*y + M(2,28)*x.*y.*y.*z + M(2,29)*x.*y.*z.*z + M(2,30)*x.*z.*z.*z + M(2,31)*y.*y.*y.*y + M(2,32)*y.*y.*y.*z + M(2,33)*y.*y.*z.*z + M(2,34)*y.*z.*z.*z + M(2,35)*z.*z.*z.*z + M(2,36)*x.*x.*x.*x.*x + M(2,37)*x.*x.*x.*x.*y + M(2,38)*x.*x.*x.*x.*z + M(2,39)*x.*x.*x.*y.*y + M(2,40)*x.*x.*x.*y.*z + M(2,41)*x.*x.*x.*z.*z + M(2,42)*x.*x.*y.*y.*y + M(2,43)*x.*x.*y.*y.*z + M(2,44)*x.*x.*y.*z.*z + M(2,45)*x.*x.*z.*z.*z + M(2,46)*x.*y.*y.*y.*y + M(2,47)*x.*y.*y.*y.*z + M(2,48)*x.*y.*y.*z.*z + M(2,49)*x.*y.*z.*z.*z + M(2,50)*x.*z.*z.*z.*z + M(2,51)*y.*y.*y.*y.*y + M(2,52)*y.*y.*y.*y.*z + M(2,53)*y.*y.*y.*z.*z + M(2,54)*y.*y.*z.*z.*z + M(2,55)*y.*z.*z.*z.*z + M(2,56)*z.*z.*z.*z.*z;
  124. zz = M(3,1) + M(3,2)*x + M(3,3)*y + M(3,4)*z + M(3,5)*x.*x + M(3,6)*x.*y + M(3,7)*x.*z + M(3,8)*y.*y + M(3,9)*y.*z + M(3,10)*z.*z + M(3,11)*x.*x.*x + M(3,12)*x.*x.*y + M(3,13)*x.*x.*z + M(3,14)*x.*y.*y + M(3,15)*x.*y.*z + M(3,16)*x.*z.*z + M(3,17)*y.*y.*y + M(3,18)*y.*y.*z + M(3,19)*y.*z.*z + M(3,20)*z.*z.*z + M(3,21)*x.*x.*x.*x + M(3,22)*x.*x.*x.*y + M(3,23)*x.*x.*x.*z + M(3,24)*x.*x.*y.*y + M(3,25)*x.*x.*y.*z + M(3,26)*x.*x.*z.*z + M(3,27)*x.*y.*y.*y + M(3,28)*x.*y.*y.*z + M(3,29)*x.*y.*z.*z + M(3,30)*x.*z.*z.*z + M(3,31)*y.*y.*y.*y + M(3,32)*y.*y.*y.*z + M(3,33)*y.*y.*z.*z + M(3,34)*y.*z.*z.*z + M(3,35)*z.*z.*z.*z + M(3,36)*x.*x.*x.*x.*x + M(3,37)*x.*x.*x.*x.*y + M(3,38)*x.*x.*x.*x.*z + M(3,39)*x.*x.*x.*y.*y + M(3,40)*x.*x.*x.*y.*z + M(3,41)*x.*x.*x.*z.*z + M(3,42)*x.*x.*y.*y.*y + M(3,43)*x.*x.*y.*y.*z + M(3,44)*x.*x.*y.*z.*z + M(3,45)*x.*x.*z.*z.*z + M(3,46)*x.*y.*y.*y.*y + M(3,47)*x.*y.*y.*y.*z + M(3,48)*x.*y.*y.*z.*z + M(3,49)*x.*y.*z.*z.*z + M(3,50)*x.*z.*z.*z.*z + M(3,51)*y.*y.*y.*y.*y + M(3,52)*y.*y.*y.*y.*z + M(3,53)*y.*y.*y.*z.*z + M(3,54)*y.*y.*z.*z.*z + M(3,55)*y.*z.*z.*z.*z + M(3,56)*z.*z.*z.*z.*z;
  125. else
  126. error('invalid size of nonlinear transformation matrix');
  127. end
  128. warped = [xx yy zz];
  129. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  130. % linear warping using homogenous coordinate transformation matrix
  131. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  132. elseif strcmp(method, 'homogenous') || strcmp(method, 'homogeneous')
  133. if all(size(M)==3)
  134. % convert the 3x3 homogenous transformation matrix (corresponding with 2D)
  135. % into a 4x4 homogenous transformation matrix (corresponding with 3D)
  136. M = [
  137. M(1,1) M(1,2) 0 M(1,3)
  138. M(2,1) M(2,2) 0 M(2,3)
  139. 0 0 0 0
  140. M(3,1) M(3,2) 0 M(3,3)
  141. ];
  142. end
  143. %warped = M * [input'; ones(1, size(input, 1))];
  144. %warped = warped(1:3,:)';
  145. % below achieves the same as lines 154-155
  146. warped = [input ones(size(input, 1),1)]*M(1:3,:)';
  147. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  148. % using external function that returns a homogeneous transformation matrix
  149. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  150. elseif exist(method, 'file') && ~isa(M, 'struct')
  151. % get the homogenous transformation matrix
  152. H = feval(method, M);
  153. warped = warp_apply(H, input, 'homogeneous');
  154. elseif strcmp(method, 'sn2individual') && isa(M, 'struct')
  155. % use SPM structure with parameters for an inverse warp
  156. % from normalized space to individual, can be non-linear
  157. warped = sn2individual(M, input);
  158. elseif strcmp(method, 'individual2sn') && isa(M, 'struct')
  159. % use SPM structure with parameters for a warp from
  160. % individual space to normalized space, can be non-linear
  161. error('individual2sn is not yet implemented');
  162. else
  163. error('unrecognized transformation method');
  164. end
  165. if ~input3d
  166. % convert from 3D back to 2D representation
  167. warped = warped(:,1:2);
  168. end
  169. if ~isempty(tol)
  170. if tol>0
  171. warped = fix(warped./tol)*tol;
  172. end
  173. end