-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathkriging.m
More file actions
218 lines (189 loc) · 6.02 KB
/
Copy pathkriging.m
File metadata and controls
218 lines (189 loc) · 6.02 KB
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
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
function [zi,s2zi] = kriging(vstruct,x,y,z,xi,yi,chunksize)
% interpolation with ordinary kriging in two dimensions
%
% Syntax:
%
% [zi,zivar] = kriging(vstruct,x,y,z,xi,yi)
% [zi,zivar] = kriging(vstruct,x,y,z,xi,yi,chunksize)
%
% Description:
%
% kriging uses ordinary kriging to interpolate a variable z measured at
% locations with the coordinates x and y at unsampled locations xi, yi.
% The function requires the variable vstruct that contains all
% necessary information on the variogram. vstruct is the forth output
% argument of the function variogramfit.
%
% This is a rudimentary, but easy to use function to perform a simple
% kriging interpolation. I call it rudimentary since it always includes
% ALL observations to estimate values at unsampled locations. This may
% not be necessary when sample locations are not within the
% autocorrelation range but would require something like a k nearest
% neighbor search algorithm or something similar. Thus, the algorithms
% works best for relatively small numbers of observations (100-500).
% For larger numbers of observations I recommend the use of GSTAT.
%
% Note that kriging fails if there are two or more observations at one
% location or very, very close to each other. This may cause that the
% system of equation is badly conditioned. Currently, I use the
% pseudo-inverse (pinv) to come around this problem. If you have better
% ideas, please let me know.
%
% Input arguments:
%
% vstruct structure array with variogram information as returned
% variogramfit (forth output argument)
% x,y coordinates of observations
% z values of observations
% xi,yi coordinates of locations for predictions
% chunksize nr of elements in zi that are processed at one time.
% The default is 100, but this depends largely on your
% available main memory and numel(x).
%
% Output arguments:
%
% zi kriging predictions
% zivar kriging variance
%
% Example:
%
% % create random field with autocorrelation
% [X,Y] = meshgrid(0:500);
% Z = randn(size(X));
% Z = imfilter(Z,fspecial('gaussian',[40 40],8));
%
% % sample the field
% n = 500;
% x = rand(n,1)*500;
% y = rand(n,1)*500;
% z = interp2(X,Y,Z,x,y);
%
% % plot the random field
% subplot(2,2,1)
% imagesc(X(1,:),Y(:,1),Z); axis image; axis xy
% hold on
% plot(x,y,'.k')
% title('random field with sampling locations')
%
% % calculate the sample variogram
% v = variogram([x y],z,'plotit',false,'maxdist',100);
% % and fit a spherical variogram
% subplot(2,2,2)
% [dum,dum,dum,vstruct] = variogramfit(v.distance,v.val,[],[],[],'model','stable');
% title('variogram')
%
% % now use the sampled locations in a kriging
% [Zhat,Zvar] = kriging(vstruct,x,y,z,X,Y);
% subplot(2,2,3)
% imagesc(X(1,:),Y(:,1),Zhat); axis image; axis xy
% title('kriging predictions')
% subplot(2,2,4)
% contour(X,Y,Zvar); axis image
% title('kriging variance')
%
%
% see also: variogram, variogramfit, consolidator, pinv
%
% Date: 28. August, 2014
% Author: Wolfgang Schwanghart (w.schwanghart[at]geo.uni-potsdam.de)
% size of input arguments
sizest = size(xi);
numest = numel(xi);
numobs = numel(x);
% force column vectors
xi = xi(:);
yi = yi(:);
x = x(:);
y = y(:);
z = z(:);
if nargin == 6;
chunksize = 100;
elseif nargin == 7;
else
error('wrong number of input arguments')
end
% check if the latest version of variogramfit is used
if ~isfield(vstruct, 'func')
error('please download the latest version of variogramfit from the FEX')
end
% variogram function definitions
switch lower(vstruct.model)
case {'whittle' 'matern'}
error('whittle and matern are not supported yet');
case 'stable'
stablealpha = vstruct.stablealpha; %#ok<NASGU> % will be used in an anonymous function
end
% distance matrix of locations with known values
Dx = hypot(bsxfun(@minus,x,x'),bsxfun(@minus,y,y'));
% if we have a bounded variogram model, it is convenient to set distances
% that are longer than the range to the range since from here on the
% variogram value remains the same and we don£t need composite functions.
switch vstruct.type;
case 'bounded'
Dx = min(Dx,vstruct.range);
otherwise
end
% now calculate the matrix with variogram values
A = vstruct.func([vstruct.range vstruct.sill],Dx);
if ~isempty(vstruct.nugget)
A = A+vstruct.nugget;
end
% the matrix must be expanded by one line and one row to account for
% condition, that all weights must sum to one (lagrange multiplier)
A = [[A ones(numobs,1)];ones(1,numobs) 0];
% A is often very badly conditioned. Hence we use the Pseudo-Inverse for
% solving the equations
A = pinv(A);
% we also need to expand z
z = [z;0];
% allocate the output zi
zi = nan(numest,1);
if nargout == 2;
s2zi = nan(numest,1);
krigvariance = true;
else
krigvariance = false;
end
% parametrize engine
nrloops = ceil(numest/chunksize);
% initialize the waitbar
h = waitbar(0,'Kr...kr...kriging');
% now loop
for r = 1:nrloops;
% waitbar
waitbar(r / nrloops,h);
% built chunks
if r<nrloops
IX = (r-1)*chunksize +1 : r*chunksize;
else
IX = (r-1)*chunksize +1 : numest;
chunksize = numel(IX);
end
% build b
b = hypot(bsxfun(@minus,x,xi(IX)'),bsxfun(@minus,y,yi(IX)'));
% again set maximum distances to the range
switch vstruct.type
case 'bounded'
b = min(vstruct.range,b);
end
% expand b with ones
b = [vstruct.func([vstruct.range vstruct.sill],b);ones(1,chunksize)];
if ~isempty(vstruct.nugget)
b = b+vstruct.nugget;
end
% solve system
lambda = A*b;
% estimate zi
zi(IX) = lambda'*z;
% calculate kriging variance
if krigvariance
s2zi(IX) = sum(b.*lambda,1);
end
end
% close waitbar
close(h)
% reshape zi
zi = reshape(zi,sizest);
if krigvariance
s2zi = reshape(s2zi,sizest);
end