From: <aba...@us...> - 2012-06-22 15:06:04
|
Revision: 10665 http://octave.svn.sourceforge.net/octave/?rev=10665&view=rev Author: abarth93 Date: 2012-06-22 15:05:53 +0000 (Fri, 22 Jun 2012) Log Message: ----------- initial import of ncArray Added Paths: ----------- trunk/octave-forge/extra/ncArray/inst/@BaseArray/ trunk/octave-forge/extra/ncArray/inst/@BaseArray/BaseArray.m trunk/octave-forge/extra/ncArray/inst/@BaseArray/end.m trunk/octave-forge/extra/ncArray/inst/@BaseArray/full.m trunk/octave-forge/extra/ncArray/inst/@BaseArray/size.m trunk/octave-forge/extra/ncArray/inst/@CatArray/ trunk/octave-forge/extra/ncArray/inst/@CatArray/CatArray.m trunk/octave-forge/extra/ncArray/inst/@CatArray/display.m trunk/octave-forge/extra/ncArray/inst/@CatArray/idx_global_local_.m trunk/octave-forge/extra/ncArray/inst/@CatArray/subsasgn.m trunk/octave-forge/extra/ncArray/inst/@CatArray/subsref.m trunk/octave-forge/extra/ncArray/inst/@ncArray/ trunk/octave-forge/extra/ncArray/inst/@ncArray/display.m trunk/octave-forge/extra/ncArray/inst/@ncArray/ncArray.m trunk/octave-forge/extra/ncArray/inst/@ncArray/ncsub.m trunk/octave-forge/extra/ncArray/inst/@ncArray/subsasgn.m trunk/octave-forge/extra/ncArray/inst/@ncArray/subsref.m trunk/octave-forge/extra/ncArray/inst/@ncData/ trunk/octave-forge/extra/ncArray/inst/@ncData/coord.m trunk/octave-forge/extra/ncArray/inst/@ncData/ncData.m trunk/octave-forge/extra/ncArray/inst/@ncData/subsasgn.m trunk/octave-forge/extra/ncArray/inst/@ncData/subsref.m Added: trunk/octave-forge/extra/ncArray/inst/@BaseArray/BaseArray.m =================================================================== --- trunk/octave-forge/extra/ncArray/inst/@BaseArray/BaseArray.m (rev 0) +++ trunk/octave-forge/extra/ncArray/inst/@BaseArray/BaseArray.m 2012-06-22 15:05:53 UTC (rev 10665) @@ -0,0 +1,7 @@ +% sz size of the array (with at least two elements) + +function retval = BaseArray(sz) + +self.sz = sz; + +retval = class(self,'BaseArray'); \ No newline at end of file Added: trunk/octave-forge/extra/ncArray/inst/@BaseArray/end.m =================================================================== --- trunk/octave-forge/extra/ncArray/inst/@BaseArray/end.m (rev 0) +++ trunk/octave-forge/extra/ncArray/inst/@BaseArray/end.m 2012-06-22 15:05:53 UTC (rev 10665) @@ -0,0 +1,3 @@ +function e = end(self,k,n) + +e = size(self,k); Added: trunk/octave-forge/extra/ncArray/inst/@BaseArray/full.m =================================================================== --- trunk/octave-forge/extra/ncArray/inst/@BaseArray/full.m (rev 0) +++ trunk/octave-forge/extra/ncArray/inst/@BaseArray/full.m 2012-06-22 15:05:53 UTC (rev 10665) @@ -0,0 +1,10 @@ +function F = full(self); + +n = length(self.sz); +idx.type = '()'; + +for i=1:n + idx.subs{i} = ':'; +end + +F = subsref(self,idx); \ No newline at end of file Added: trunk/octave-forge/extra/ncArray/inst/@BaseArray/size.m =================================================================== --- trunk/octave-forge/extra/ncArray/inst/@BaseArray/size.m (rev 0) +++ trunk/octave-forge/extra/ncArray/inst/@BaseArray/size.m 2012-06-22 15:05:53 UTC (rev 10665) @@ -0,0 +1,8 @@ +function sz = size(self,dim) + +sz = self.sz; + +if nargin == 2 + sz = sz(dim); +end + Added: trunk/octave-forge/extra/ncArray/inst/@CatArray/CatArray.m =================================================================== --- trunk/octave-forge/extra/ncArray/inst/@CatArray/CatArray.m (rev 0) +++ trunk/octave-forge/extra/ncArray/inst/@CatArray/CatArray.m 2012-06-22 15:05:53 UTC (rev 10665) @@ -0,0 +1,70 @@ +% C = CatArray(dim,{array1,array2,...}) +% +% Create a concatenated array from a cell-list of arrays. Individual +% elements can be accessed by subscribs, e.g.: +% C(2,3) + + +function retval = CatArray(dim,arrays) + +self.dim = dim; +self.arrays = arrays; +self.na = length(arrays); + +% number of dimensions +self.nd = length(size(arrays{1})); +if dim > self.nd + self.nd = dim; +end + +self.size = ones(self.na,self.nd); +self.start = ones(self.na,self.nd); + +% get size of all arrays +for i=1:self.na + tmp = size(arrays{i}); + self.size(i,1:length(tmp)) = tmp; +end + +% check if dimensions are consistent +ncd = 1:self.nd ~= dim; +for i=2:self.na + if ~all(self.size(i,ncd) == self.size(1,ncd)) + error('Array number %d has inconsistent dimension',i); + end +end + +% start index of each sub-array + +for i=2:self.na + self.start(i,:) = self.start(i-1,:); + self.start(i,dim) = self.start(i,dim) + self.size(i-1,dim); +end + +self.end = self.start + self.size - 1; + +self.sz = self.size(1,:); +self.sz(dim) = sum(self.size(:,dim)); +self.overlap = false; +self.bounds = [0; cumsum(prod(self.size,2))]; + +retval = class(self,'CatArray',BaseArray(self.sz)); + + +% Copyright (C) 2012 Alexander Barth <bar...@gm...> +% +% This program is free software; you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation; either version 2 of the License, or +% (at your option) any later version. +% +% This program is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with this program; If not, see <http://www.gnu.org/licenses/>. + + + Added: trunk/octave-forge/extra/ncArray/inst/@CatArray/display.m =================================================================== --- trunk/octave-forge/extra/ncArray/inst/@CatArray/display.m (rev 0) +++ trunk/octave-forge/extra/ncArray/inst/@CatArray/display.m 2012-06-22 15:05:53 UTC (rev 10665) @@ -0,0 +1,6 @@ +function display(self) + +for i=1:self.na + display(self.arrays{i}) +end + \ No newline at end of file Added: trunk/octave-forge/extra/ncArray/inst/@CatArray/idx_global_local_.m =================================================================== --- trunk/octave-forge/extra/ncArray/inst/@CatArray/idx_global_local_.m (rev 0) +++ trunk/octave-forge/extra/ncArray/inst/@CatArray/idx_global_local_.m 2012-06-22 15:05:53 UTC (rev 10665) @@ -0,0 +1,58 @@ +% private method + +function [idx_global,idx_local,sz] = idx_global_local_(self,idx) + +assert(strcmp(idx.type,'()')) + +n = length(size(self)); + +% number of indices must be equal to dimension +assert(length(idx.subs) == n) + +lb = ones(1,n); % lower bound +ub = ones(1,n); % upper bound +sz = ones(1,n); % size + +% transform all colons to index range +for i=1:n + if strcmp(idx.subs{i},':') + idx.subs{i} = 1:self.sz(i); + end + + lb(i) = min(idx.subs{i}); + ub(i) = max(idx.subs{i}); + sz(i) = length(idx.subs{i}); +end + +%sz = ub-lb+1; + +idx_local = cell(1,self.na); +idx_global = cell(1,self.na); + +% loop over all arrays +for j=1:self.na + idx_local{j} = idx; + idx_global{j} = idx; + + % loop over all dimensions + for i=1:n + % rebase subscribt at self.start(j,i) + tmp = idx.subs{i} - self.start(j,i) + 1; + + % only indeces within bounds of the j-th array + sel = 1 <= tmp & tmp <= self.size(j,i); + + % index for getting the data from the local j-th array + idx_local{j}.subs{i} = tmp(sel); + + % index for setting the data in the global B array + %idx_global{j}.subs{i} = idx.subs{i}(sel) - lb(i)+1; + + if sum(sel) == 0 + idx_global{j}.subs{i} = []; + else + idx_global{j}.subs{i} = (1:sum(sel)) + find(sel,1,'first') - 1; + end + end + +end Added: trunk/octave-forge/extra/ncArray/inst/@CatArray/subsasgn.m =================================================================== --- trunk/octave-forge/extra/ncArray/inst/@CatArray/subsasgn.m (rev 0) +++ trunk/octave-forge/extra/ncArray/inst/@CatArray/subsasgn.m 2012-06-22 15:05:53 UTC (rev 10665) @@ -0,0 +1,14 @@ +function self = subsasgn(self,idx,x) + +[idx_global,idx_local,sz] = idx_global_local_(self,idx); + + + + +for j=1:self.na + % get subset from global array x + subset = subsref(x,idx_global{j}); + + % set subset in j-th array + subsasgn(self.arrays{j},idx_local{j},subset); +end \ No newline at end of file Added: trunk/octave-forge/extra/ncArray/inst/@CatArray/subsref.m =================================================================== --- trunk/octave-forge/extra/ncArray/inst/@CatArray/subsref.m (rev 0) +++ trunk/octave-forge/extra/ncArray/inst/@CatArray/subsref.m 2012-06-22 15:05:53 UTC (rev 10665) @@ -0,0 +1,79 @@ +function B = subsref(self,idx) + +% handle case with a single subscript +% for example CA(234) + +if strcmp(idx.type,'()') && length(idx.subs) == 1 + % indices of elements in B + ind = idx.subs{1}; + + % output array + B = zeros(size(ind)); + B(:) = NaN; + + if self.overlap + % transform index to subscript + subs = cell(1,self.nd); + [subs{:}] = ind2sub(size(self),ind); + + % make a nice array length(ind) by self.nd + subs = cell2mat(subs); + + + % get every element + idxe.type = '()'; + idxe.subs = cell(1,self.nd); + + for i=1:length(ind) + idxe.subs = mat2cell(subs(i,:),1,ones(1,self.nd)); + %B(i) = subsref_canonical(self,idxe); + + [idx_global,idx_local,sz] = idx_global_local_(self,idxe); + tmp = zeros(sz); + tmp(:) = NaN; + + + for j=1:self.na + % get subset from j-th array + subset = subsref(self.arrays{j},idx_local{j}); + + % set subset in global array B + tmp = subsasgn(tmp,idx_global{j},subset); + end + B(i) = tmp; + + end + else + % assume all arrays does not overlap + + for j=1:self.na + sel = self.bounds(j) < ind & ind <= self.bounds(j+1); + B(sel) = self.arrays{j}(ind(sel) - self.bounds(j)); + end + + end + +else + B = subsref_canonical(self,idx); +end + +end + +% for this function we assume that idx.subs has the same dimension than +% the array + +function B = subsref_canonical(self,idx) +[idx_global,idx_local,sz] = idx_global_local_(self,idx); + +B = zeros(sz); +B(:) = NaN; + +for j=1:self.na + % get subset from j-th array + subset = subsref(self.arrays{j},idx_local{j}); + + % set subset in global array B + B = subsasgn(B,idx_global{j},subset); +end + +end \ No newline at end of file Added: trunk/octave-forge/extra/ncArray/inst/@ncArray/display.m =================================================================== --- trunk/octave-forge/extra/ncArray/inst/@ncArray/display.m (rev 0) +++ trunk/octave-forge/extra/ncArray/inst/@ncArray/display.m 2012-06-22 15:05:53 UTC (rev 10665) @@ -0,0 +1,4 @@ +function display(self) +disp([self.varname ' from ' self.filename]); +%self.vinfo +%self.dims Added: trunk/octave-forge/extra/ncArray/inst/@ncArray/ncArray.m =================================================================== --- trunk/octave-forge/extra/ncArray/inst/@ncArray/ncArray.m (rev 0) +++ trunk/octave-forge/extra/ncArray/inst/@ncArray/ncArray.m 2012-06-22 15:05:53 UTC (rev 10665) @@ -0,0 +1,61 @@ +% V = ncArray(filename,varname) +% V = ncArray(filename,varname,'property',value,...) +% create a ncArray that can be accessed as a normal matlab array. +% +% For read access filename can be compressed if it has the extensions +% ".gz" or ".bz2". It use the function cache_decompress to cache to +% decompressed files. +% +% Data is loaded by ncread and saved by ncwrite. Values equal to _FillValue +% are thus replaced by NaN and the scaling (add_offset and +% scale_factor) is applied during loading and saving. +% +% Properties: +% 'tooBigToLoad': if tooBigToLoad is set to true, then only the minimum +% data will be loaded. However this can be quite slow. +% +% Example: +% +% Loading the variable (assuming V is 3 dimensional): +% +% x = V(1,1,1); % load element 1,1,1 +% x = V(:,:,:); % load the complete array +% x = V(); x = full(V) % loads also the complete array +% +% Saving data in the netcdf file: +% V(1,1,1) = x; % save x in element 1,1,1 +% V(:,:,:) = x; +% +% Attributes +% units = V.units; % get attribute called "units" +% V.units = 'degree C'; % set attributes; +% +% Note: use the '.()' notation if the attribute has a leading underscore +% (due to a limitation in the matlab parser): +% +% V.('_someStrangeAttribute') = 123; +% +% see also cache_decompress + +function retval = ncArray(filename,varname,varargin) + +self.tooBigToLoad = false; +prop = varargin; + +for i=1:2:length(prop) + if strcmp(prop{i},'tooBigToLoad ') + self.tooBigToLoad = prop{i+1}; + end +end + +self.filename = filename; +self.varname = varname; + +self.vinfo = ncinfo(cached_decompress(filename),varname); +self.sz = self.vinfo.Size; + +self.dims = self.vinfo.Dimensions; +self.nd = length(self.dims); + +retval = class(self,'ncArray',BaseArray(self.sz)); +end Added: trunk/octave-forge/extra/ncArray/inst/@ncArray/ncsub.m =================================================================== --- trunk/octave-forge/extra/ncArray/inst/@ncArray/ncsub.m (rev 0) +++ trunk/octave-forge/extra/ncArray/inst/@ncArray/ncsub.m 2012-06-22 15:05:53 UTC (rev 10665) @@ -0,0 +1,61 @@ +function [start, count, stride] = ncsub(self,idx) + +assert(strcmp(idx.type,'()')) + +% number of dimension (including singleton dimensions) +%n = length(size(self)); +n = self.nd; + +% number of subscripts +ns = length(idx.subs); + +if ns == 0 + % load all + start = ones(1,n); + count = self.sz; + stride = ones(1,n); +else + + start = ones(1,ns); + count = ones(1,ns); + stride = ones(1,ns); + + % sz is the size padded by 1 if more indices are given than n + sz = ones(1,ns); + sz(1:length(self.sz)) = self.sz; + + for i=1:ns + if isempty(idx.subs{i}) + count(i) = 0; + + elseif strcmp(idx.subs{i},':') + count(i) = sz(i); + + else + tmp = idx.subs{i}; + + if length(tmp) == 1 + start(i) = tmp; + else + test = tmp(1):tmp(2)-tmp(1):tmp(end); + + if all(tmp == test) + start(i) = tmp(1); + stride(i) = tmp(2)-tmp(1); + count(i) = (tmp(end)-tmp(1))/stride(i) +1; + else + error('indeces'); + end + end + end + end + + assert(all(count(n+1:end) == 1 | count(n+1:end) == 0)) + assert(all(start(n+1:end) == 1)) + + if ~any(count == 0) + count = count(1:n); + start = start(1:n); + stride = stride(1:n); + end +end \ No newline at end of file Added: trunk/octave-forge/extra/ncArray/inst/@ncArray/subsasgn.m =================================================================== --- trunk/octave-forge/extra/ncArray/inst/@ncArray/subsasgn.m (rev 0) +++ trunk/octave-forge/extra/ncArray/inst/@ncArray/subsasgn.m 2012-06-22 15:05:53 UTC (rev 10665) @@ -0,0 +1,10 @@ +function self = subsasgn(self,idxs,x) +%idx + +idx = idxs(1); +assert(strcmp(idx.type,'()')) +[start, count, stride] = ncsub(self,idx); + +if all(count ~= 0) + ncwrite(self.filename,self.varname,x,start,stride); +end Added: trunk/octave-forge/extra/ncArray/inst/@ncArray/subsref.m =================================================================== --- trunk/octave-forge/extra/ncArray/inst/@ncArray/subsref.m (rev 0) +++ trunk/octave-forge/extra/ncArray/inst/@ncArray/subsref.m 2012-06-22 15:05:53 UTC (rev 10665) @@ -0,0 +1,65 @@ +function x = subsref(self,idx) + +assert(length(idx) == 1) + +if strcmp(idx.type,'()') + % load data + + if strcmp(idx.type,'()') && length(idx.subs) == 1 ... + && length(idx.subs) < self.nd + % reference like A([2 3 1 5]) + + if self.tooBigToLoad + % number of elements in x + ind = idx.subs{1}; + + % transform index to subscript + subs = cell(1,self.nd); + [subs{:}] = ind2sub(size(self),ind); + + % make a nice array length(ind) by self.nd + subs = cell2mat(subs); + + % output array + x = zeros(size(ind)); + x(:) = NaN; + + + % get every element + % can be quite slow + idxe.type = '()'; + idxe.subs = cell(1,self.nd); + + for i=1:length(ind) + idxe.subs = mat2cell(subs(i,:),1,ones(1,self.nd)); + x(i) = subsref(self,idxe); + end + else + % load full array + tmp = full(self); + x = subsref(tmp,idx); + end + else + [start, count, stride] = ncsub(self,idx); + + if any(count == 0) + x = zeros(count); + else + x = ncread(cached_decompress(self.filename),self.varname,... + start,count,stride); + end + end +elseif strcmp(idx.type,'.') + % load attribute + name = idx.subs; + index = strmatch(name,{self.vinfo.Attributes(:).Name}); + + if isempty(index) + error('variable %s has no attribute called %s',self.varname,name); + else + x = self.vinfo.Attributes(index).Value; + end +else + error('not supported'); + +end \ No newline at end of file Added: trunk/octave-forge/extra/ncArray/inst/@ncData/coord.m =================================================================== --- trunk/octave-forge/extra/ncArray/inst/@ncData/coord.m (rev 0) +++ trunk/octave-forge/extra/ncArray/inst/@ncData/coord.m 2012-06-22 15:05:53 UTC (rev 10665) @@ -0,0 +1,3 @@ +function c = coord(self) +c = self.coord; +%'her' \ No newline at end of file Added: trunk/octave-forge/extra/ncArray/inst/@ncData/ncData.m =================================================================== --- trunk/octave-forge/extra/ncArray/inst/@ncData/ncData.m (rev 0) +++ trunk/octave-forge/extra/ncArray/inst/@ncData/ncData.m 2012-06-22 15:05:53 UTC (rev 10665) @@ -0,0 +1,30 @@ +% data = ncData(filename,varname) +% data = ncData(var,dims,coord) +% data with coordinate values + +function retval = ncData(varargin) + +if ischar(varargin{1}) + filename = varargin{1}; + varname = varargin{2}; + var = ncArray(filename,varname); + [dims,coord] = nccoord(cached_decompress(filename),varname); + + for i=1:length(coord) + coord(i).val = ncArray(filename,coord(i).name); + end +else + var = varargin{1}; + dims = varargin{2}; + coord = varargin{3}; +end + +self.var = var; +self.dims = dims; +self.nd = length(self.dims); +self.coord = coord; + +retval = class(self,'ncData',BaseArray(size(self.var))); + + + Added: trunk/octave-forge/extra/ncArray/inst/@ncData/subsasgn.m =================================================================== --- trunk/octave-forge/extra/ncArray/inst/@ncData/subsasgn.m (rev 0) +++ trunk/octave-forge/extra/ncArray/inst/@ncData/subsasgn.m 2012-06-22 15:05:53 UTC (rev 10665) @@ -0,0 +1,3 @@ +function self = subsasgn(self,idx,x) + +self = subsasgn(self.var,idx,x); Added: trunk/octave-forge/extra/ncArray/inst/@ncData/subsref.m =================================================================== --- trunk/octave-forge/extra/ncArray/inst/@ncData/subsref.m (rev 0) +++ trunk/octave-forge/extra/ncArray/inst/@ncData/subsref.m 2012-06-22 15:05:53 UTC (rev 10665) @@ -0,0 +1,32 @@ +function varargout = subsref(self,idx) + +if strcmp(idx(1).type,'()') + + % no subscripts mean that we load all () -> (:,:,...) + if isempty(idx(1).subs) + for i=1:self.nd + idx(1).subs{i} = ':'; + end + end +end + +% catch expressions like: +% data(:,:,:).coord + +if length(idx) == 2 && strcmp(idx(2).type,'.') && strcmp(idx(2).subs,'coord') + for i=1:length(self.coord) + % get indeces of the dimensions of the i-th coordinate which are also + % coordinate of the variable + + % replace dummy by ~ once older version have died + [dummy,j] = intersect(self.dims,self.coord(i).dims); + j = sort(j); + idx_c.type = '()'; + idx_c.subs = idx(1).subs(j); + + varargout{i} = subsref(self.coord(i).val,idx_c); + end +else + % pass subsref to underlying ncArray + varargout{1} = subsref(self.var,idx); +end \ No newline at end of file This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |