📄 gridfit.m
字号:
end endend % if params.tilesize...% only generate xgrid and ygrid if requested.if nargout>1 [xgrid,ygrid]=meshgrid(xnodes,ynodes);end% ============================================% End of main function - gridfit% ============================================% ============================================% subfunction - parse_pv_pairs% ============================================function params=parse_pv_pairs(params,pv_pairs)% parse_pv_pairs: parses sets of property value pairs, allows defaults% usage: params=parse_pv_pairs(default_params,pv_pairs)%% arguments: (input)% default_params - structure, with one field for every potential% property/value pair. Each field will contain the default% value for that property. If no default is supplied for a% given property, then that field must be empty.%% pv_array - cell array of property/value pairs.% Case is ignored when comparing properties to the list% of field names. Also, any unambiguous shortening of a% field/property name is allowed.%% arguments: (output)% params - parameter struct that reflects any updated property/value% pairs in the pv_array.%% Example usage:% First, set default values for the parameters. Assume we% have four parameters that we wish to use optionally in% the function examplefun.%% - 'viscosity', which will have a default value of 1% - 'volume', which will default to 1% - 'pie' - which will have default value 3.141592653589793% - 'description' - a text field, left empty by default%% The first argument to examplefun is one which will always be% supplied.%% function examplefun(dummyarg1,varargin)% params.Viscosity = 1;% params.Volume = 1;% params.Pie = 3.141592653589793%% params.Description = '';% params=parse_pv_pairs(params,varargin);% params%% Use examplefun, overriding the defaults for 'pie', 'viscosity'% and 'description'. The 'volume' parameter is left at its default.%% examplefun(rand(10),'vis',10,'pie',3,'Description','Hello world')%% params = % Viscosity: 10% Volume: 1% Pie: 3% Description: 'Hello world'%% Note that capitalization was ignored, and the property 'viscosity'% was truncated as supplied. Also note that the order the pairs were% supplied was arbitrary.npv = length(pv_pairs);n = npv/2;if n~=floor(n) error 'Property/value pairs must come in PAIRS.'endif n<=0 % just return the defaults returnendif ~isstruct(params) error 'No structure for defaults was supplied'end% there was at least one pv pair. process any suppliedpropnames = fieldnames(params);lpropnames = lower(propnames);for i=1:n p_i = lower(pv_pairs{2*i-1}); v_i = pv_pairs{2*i}; ind = strmatch(p_i,lpropnames,'exact'); if isempty(ind) ind = find(strncmp(p_i,lpropnames,length(p_i))); if isempty(ind) error(['No matching property found for: ',pv_pairs{2*i-1}]) elseif length(ind)>1 error(['Ambiguous property name: ',pv_pairs{2*i-1}]) end end p_i = propnames{ind}; % override the corresponding default in params params = setfield(params,p_i,v_i); %#ok end% ============================================% subfunction - check_params% ============================================function params = check_params(params)% check the parameters for acceptability% smoothness == 1 by defaultif isempty(params.smoothness) params.smoothness = 1;else if (length(params.smoothness)>1) || (params.smoothness<=0) error 'Smoothness must be scalar, real, finite, and positive.' endend% regularizer - must be one of 4 options - the second and% third are actually synonyms.valid = {'springs', 'diffusion', 'laplacian', 'gradient'};if isempty(params.regularizer) params.regularizer = 'diffusion';endind = find(strncmpi(params.regularizer,valid,length(params.regularizer)));if (length(ind)==1) params.regularizer = valid{ind};else error(['Invalid regularization method: ',params.regularizer])end% interp must be one of:% 'bilinear', 'nearest', or 'triangle'% but accept any shortening thereof.valid = {'bilinear', 'nearest', 'triangle'};if isempty(params.interp) params.interp = 'triangle';endind = find(strncmpi(params.interp,valid,length(params.interp)));if (length(ind)==1) params.interp = valid{ind};else error(['Invalid interpolation method: ',params.interp])end% solver must be one of:% 'backslash', '\', 'symmlq', 'lsqr', or 'normal'% but accept any shortening thereof.valid = {'backslash', '\', 'symmlq', 'lsqr', 'normal'};if isempty(params.solver) params.solver = '\';endind = find(strncmpi(params.solver,valid,length(params.solver)));if (length(ind)==1) params.solver = valid{ind};else error(['Invalid solver option: ',params.solver])end% extend must be one of:% 'never', 'warning', 'always'% but accept any shortening thereof.valid = {'never', 'warning', 'always'};if isempty(params.extend) params.extend = 'warning';endind = find(strncmpi(params.extend,valid,length(params.extend)));if (length(ind)==1) params.extend = valid{ind};else error(['Invalid extend option: ',params.extend])end% tilesize == inf by defaultif isempty(params.tilesize) params.tilesize = inf;elseif (length(params.tilesize)>1) || (params.tilesize<3) error 'Tilesize must be scalar and > 0.'end% overlap == 0.20 by defaultif isempty(params.overlap) params.overlap = 0.20;elseif (length(params.overlap)>1) || (params.overlap<0) || (params.overlap>0.5) error 'Overlap must be scalar and 0 < overlap < 1.'end% ============================================% subfunction - tiled_gridfit% ============================================function zgrid=tiled_gridfit(x,y,z,xnodes,ynodes,params)% tiled_gridfit: a tiled version of gridfit, continuous across tile boundaries % usage: [zgrid,xgrid,ygrid]=tiled_gridfit(x,y,z,xnodes,ynodes,params)%% Tiled_gridfit is used when the total grid is far too large% to model using a single call to gridfit. While gridfit may take% only a second or so to build a 100x100 grid, a 2000x2000 grid% will probably not run at all due to memory problems.%% Tiles in the grid with insufficient data (<4 points) will be% filled with NaNs. Avoid use of too small tiles, especially% if your data has holes in it that may encompass an entire tile.%% A mask may also be applied, in which case tiled_gridfit will% subdivide the mask into tiles. Note that any boolean mask% provided is assumed to be the size of the complete grid.%% Tiled_gridfit may not be fast on huge grids, but it should run% as long as you use a reasonable tilesize. 8-)% Note that we have already verified all parameters in check_params% Matrix elements in a square tiletilesize = params.tilesize;% Size of overlap in terms of matrix elements. Overlaps% of purely zero cause problems, so force at least two% elements to overlap.overlap = max(2,floor(tilesize*params.overlap));% reset the tilesize for each particular tile to be inf, so% we will never see a recursive call to tiled_gridfitTparams = params;Tparams.tilesize = inf;nx = length(xnodes);ny = length(ynodes);zgrid = zeros(ny,nx);% linear ramp for the bilinear interpolationrampfun = inline('(t-t(1))/(t(end)-t(1))','t');% loop over each tile in the gridh = waitbar(0,'Relax and have a cup of JAVA. Its my treat.');warncount = 0;xtind = 1:min(nx,tilesize);while ~isempty(xtind) && (xtind(1)<=nx) xinterp = ones(1,length(xtind)); if (xtind(1) ~= 1) xinterp(1:overlap) = rampfun(xnodes(xtind(1:overlap))); end if (xtind(end) ~= nx) xinterp((end-overlap+1):end) = 1-rampfun(xnodes(xtind((end-overlap+1):end))); end ytind = 1:min(ny,tilesize); while ~isempty(ytind) && (ytind(1)<=ny) % update the waitbar waitbar((xtind(end)-tilesize)/nx + tilesize*ytind(end)/ny/nx) yinterp = ones(length(ytind),1); if (ytind(1) ~= 1) yinterp(1:overlap) = rampfun(ynodes(ytind(1:overlap))); end if (ytind(end) ~= ny) yinterp((end-overlap+1):end) = 1-rampfun(ynodes(ytind((end-overlap+1):end))); end % was a mask supplied? if ~isempty(params.mask) submask = params.mask(ytind,xtind); Tparams.mask = submask; end % extract data that lies in this grid tile k = (x>=xnodes(xtind(1))) & (x<=xnodes(xtind(end))) & ... (y>=ynodes(ytind(1))) & (y<=ynodes(ytind(end))); k = find(k); if length(k)<4 if warncount == 0 warning 'A tile was too underpopulated to model. Filled with NaNs.' end warncount = warncount + 1; % fill this part of the grid with NaNs zgrid(ytind,xtind) = NaN; else % build this tile zgtile = gridfit(x(k),y(k),z(k),xnodes(xtind),ynodes(ytind),Tparams); % bilinear interpolation (using an outer product) interp_coef = yinterp*xinterp; % accumulate the tile into the complete grid zgrid(ytind,xtind) = zgrid(ytind,xtind) + zgtile.*interp_coef; end % step to the next tile in y if ytind(end)<ny ytind = ytind + tilesize - overlap; % are we within overlap elements of the edge of the grid? if (ytind(end)+max(3,overlap))>=ny % extend this tile to the edge ytind = ytind(1):ny; end else ytind = ny+1; end end % while loop over y % step to the next tile in x if xtind(end)<nx xtind = xtind + tilesize - overlap; % are we within overlap elements of the edge of the grid? if (xtind(end)+max(3,overlap))>=nx % extend this tile to the edge xtind = xtind(1):nx; end else xtind = nx+1; endend % while loop over x% close down the waitbarclose(h)if warncount>0 warning([num2str(warncount),' tiles were underpopulated & filled with NaNs'])end
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -