-
Notifications
You must be signed in to change notification settings - Fork 16
/
phasegradientMATLAB.m
189 lines (169 loc) · 5.76 KB
/
phasegradientMATLAB.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
function varargout = phasegradientMATLAB(f,angleFlag,varargin)
% Slight modification of MATLAB's gradient function to optionally function
% on angular data
% Rory Townsend 2017
%
% [FX,FY] = GRADIENT(F) returns the numerical gradient of the
% matrix F. FX corresponds to dF/dx, the differences in x (horizontal)
% direction. FY corresponds to dF/dy, the differences in y (vertical)
% direction. The spacing between points in each direction is assumed to
% be one. When F is a vector, DF = GRADIENT(F) is the 1-D gradient.
%
% [FX,FY] = GRADIENT(F,H), where H is a scalar, uses H as the
% spacing between points in each direction.
%
% [FX,FY] = GRADIENT(F,HX,HY), when F is 2-D, uses the spacing
% specified by HX and HY. HX and HY can either be scalars to specify
% the spacing between coordinates or vectors to specify the
% coordinates of the points. If HX and HY are vectors, their length
% must match the corresponding dimension of F.
%
% [FX,FY,FZ] = GRADIENT(F), when F is a 3-D array, returns the
% numerical gradient of F. FZ corresponds to dF/dz, the differences
% in the z direction. GRADIENT(F,H), where H is a scalar,
% uses H as the spacing between points in each direction.
%
% [FX,FY,FZ] = GRADIENT(F,HX,HY,HZ) uses the spacing given by
% HX, HY, HZ.
%
% [FX,FY,FZ,...] = GRADIENT(F,...) extends similarly when F is N-D
% and must be invoked with N outputs and either 2 or N+1 inputs.
%
% Note: The first output FX is always the gradient along the 2nd
% dimension of F, going across columns. The second output FY is always
% the gradient along the 1st dimension of F, going across rows. For the
% third output FZ and the outputs that follow, the Nth output is the
% gradient along the Nth dimension of F.
%
% Examples:
% [x,y] = meshgrid(-2:.2:2, -2:.2:2);
% z = x .* exp(-x.^2 - y.^2);
% [px,py] = gradient(z,.2,.2);
% contour(z), hold on, quiver(px,py), hold off
%
% Class support for input F:
% float: double, single
%
% See also DIFF, DEL2.
% Copyright 1984-2015 The MathWorks, Inc.
[f,ndim,loc,rflag] = parse_inputs(f,varargin);
nargoutchk(0,ndim);
% Loop over each dimension.
varargout = cell(1,ndim);
siz = size(f);
% first dimension
g = zeros(size(f),class(f)); % case of singleton dimension
h = loc{1}(:);
n = siz(1);
% Take forward differences on left and right edges
if n > 1
g(1,:) = anglesubtract(f(2,:), f(1,:), angleFlag)/(h(2)-h(1));
g(n,:) = anglesubtract(f(n,:), f(n-1,:), angleFlag)/(h(end)-h(end-1));
end
% Take centered differences on interior points
if n > 2
g(2:n-1,:) = anglesubtract(f(3:n,:), f(1:n-2,:), angleFlag) ./ (h(3:n) - h(1:n-2));
end
varargout{1} = g;
% second dimensions and beyond
if ndim == 2
% special case 2-D matrices to support sparse matrices,
% which lack support for N-D operations including reshape
% and indexing
n = siz(2);
h = reshape(loc{2},1,[]);
g = zeros(size(f),class(f));
% Take forward differences on left and right edges
if n > 1
g(:,1) = anglesubtract(f(:,2), f(:,1), angleFlag)/(h(2)-h(1));
g(:,n) = anglesubtract(f(:,n), f(:,n-1), angleFlag)/(h(end)-h(end-1));
end
% Take centered differences on interior points
if n > 2
h = h(3:n) - h(1:n-2);
g(:,2:n-1) = anglesubtract(f(:,3:n), f(:,1:n-2), angleFlag) ./ h;
end
varargout{2} = g;
elseif ndim > 2
% N-D case
for k = 2:ndim
n = siz(k);
newsiz = [prod(siz(1:k-1)) siz(k) prod(siz(k+1:end))];
nf = reshape(f,newsiz);
h = reshape(loc{k},1,[]);
g = zeros(size(nf),class(nf)); % case of singleton dimension
% Take forward differences on left and right edges
if n > 1
g(:,1,:) = anglesubtract(nf(:,2,:), nf(:,1,:), angleFlag)/(h(2)-h(1));
g(:,n,:) = anglesubtract(nf(:,n,:), nf(:,n-1,:), angleFlag)/(h(end)-h(end-1));
end
% Take centered differences on interior points
if n > 2
h = h(3:n) - h(1:n-2);
g(:,2:n-1,:) = anglesubtract(nf(:,3:n,:), nf(:,1:n-2,:), angleFlag) ./ h;
end
varargout{k} = reshape(g,siz);
end
end
% Swap 1 and 2 since x is the second dimension and y is the first.
if ndim > 1
varargout(2:-1:1) = varargout(1:2);
elseif rflag
varargout{1} = varargout{1}.';
end
%-------------------------------------------------------
function [f,ndim,loc,rflag] = parse_inputs(f,v)
%PARSE_INPUTS
% [ERR,F,LOC,RFLAG] = PARSE_INPUTS(F,V) returns the spacing
% LOC along the x,y,z,... directions and a row vector
% flag RFLAG.
loc = {};
% Flag vector case and row vector case.
ndim = ndims(f);
vflag = false;
rflag = false;
if isvector(f)
ndim = 1;
vflag = true;
if isrow(f) % Treat row vector as a column vector
rflag = true;
f = f.';
end
end;
indx = size(f);
% Default step sizes: hx = hy = hz = 1
if isempty(v)
% gradient(f)
loc = cell(1, ndims(f));
for k = 1:ndims(f)
loc(k) = {1:indx(k)};
end
elseif isscalar(v) % gradient(f,h)
% Expand scalar step size
if isscalar(v{1})
loc = cell(1, ndims(f));
for k = 1:ndims(f)
h = v{1};
loc(k) = {h*(1:indx(k))};
end
% Check for vector case
elseif vflag
loc(1) = v(1);
else
error(message('MATLAB:gradient:InvalidInputs'));
end
elseif ndims(f) == numel(v) % gradient(f,hx,hy,hz,...)
% Swap 1 and 2 since x is the second dimension and y is the first.
loc = v;
if ndim > 1
loc(2:-1:1) = loc(1:2);
end
% replace any scalar step-size with corresponding position vector
for k = 1:ndims(f)
if isscalar(loc{k})
loc{k} = loc{k}*(1:indx(k));
end
end
else
error(message('MATLAB:gradient:InvalidInputs'));
end