Code covered by the BSD License  

Highlights from
operationOnTwoFields

image thumbnail

operationOnTwoFields

by

 

17 May 2012 (Updated )

A simple mathematical operation like subtracting on two 2d fields with multiple scalar values.

operationOnTwoFields(fieldOne, fieldTwo, operator, varargin)
function [resultingField, fieldTwoInt] = operationOnTwoFields(fieldOne, fieldTwo, operator, varargin)

%Performs a mathematical operation on two fields and returns the resulting
%field as well as the interpolated second field.
%
%[resultingField, fieldTwoInt] = operationOnTwoFields(fieldOne, fieldTwo, operator)
%
%Takes two fields as an input, which must have the following format:
%
%field = [x y value1 value2 ... valueN]
%
%with each entry being a column vector. This will be as well the format of
%the resultingField. fieldOne is the reference field on which fieldTwo will
%be interpolated. Extrapolation is done only when using the 'nearest'
%interpolation (see below), otherwise the resultingField will be the planar
%intersection of both inputs. The following operation will be performed per
%column (value1 ... valueN):
%
%resultingField = fieldOne operator fieldTwoInterp
%
%The operator needs to be passed as a string ('./', '*', '+', '-', etc.)
%and since it is an eval() construct, every operator that works the
%aforementioned way should work. 'none' will return an
%empty resultingField.
%
%operationOnTwoFields(..., interpolationMethod)
%
%Optional call to the interpolation method used by TriScatteredInterp,
%default is 'linear', options are (from '$help TriScatteredInterp'):
%
%       'natural'   Natural neighbor interpolation
%       'linear'    Linear interpolation
%       'nearest'   Nearest neighbor interpolation
%
%NaNs will be removed from the input data since TriScatteredInterp doesn't
%work with NaNs.
%
%
%by Bastian Tietjen, released March 2013 under a Simplified BSD licence.


%--------set defaults---------------------------------------------
%check for more than one optional input
numberOfVarArgs = length(varargin);
if numberOfVarArgs > 1
    error('operationOnTwoFields:TooManyInputs', ...
        'just one optional input');
end

%set default values
optionalArgs = {'linear'};

%overwrite the defaults depending on the number of optional inputs
optionalArgs(1:numberOfVarArgs) = varargin;

%place the optionalArgs in variables
[interpolationMethod] = optionalArgs{:};
%--------set defaults end-----------------------------------------


%check if fieldOne and fieldTwo contain the same number of columns
if size(fieldOne,2) == size(fieldTwo,2)
    %they have the same size
    if size(fieldOne,2) <= 2 && ~strcmp('none', operator)
        %means it just contains position data, return fieldOne
        resultingField = fieldOne;
        fieldTwoInt = fieldOne;
        return
    elseif size(fieldOne,2) <= 2 && strcmp('none', operator)
        %means it just contains position data, return an empty
        %resultingField and the position data of fieldOne
        resultingField = [];
        fieldTwoInt = fieldOne;
        return
    end
else
    error('operationOnTwoFields:ColumnNumberMismatch',...
        'fieldOne and fieldTwo do not have the same number of columns');
end

%remove the NaNs from the input
fieldOne = removeNans(fieldOne);
fieldTwo = removeNans(fieldTwo);


if ~strcmp('none', operator)
    %initialize resultingField, copy positions
    resultingField = zeros(size(fieldOne));
    resultingField(:,1:2) = fieldOne(:,1:2);
else
    %if 'none' was chosen as an operator, do not initialize the resultingField
    %but set it to empty
    resultingField = [];
end

%initialize fieldTwoInt, copy positions
fieldTwoInt = zeros(size(fieldOne));
fieldTwoInt(:,1:2) = fieldOne(:,1:2);

for n = 3:size(fieldOne, 2)
    
    %interpolant for nth column of fieldTwo
    F = TriScatteredInterp(fieldTwo(:,1), fieldTwo(:,2), fieldTwo(:,n), interpolationMethod);
    
    %interpolated values of nth column of fieldTwo
    fieldTwoInt(:,n) = F(fieldOne(:,1), fieldOne(:,2));
    
    if ~strcmp('none', operator)
        %f3 = f1 operation f2
        resultingField(:,n) = eval(['fieldOne(:,n) ', operator, ' fieldTwoInt(:,n)']);
    end
    
end

%remove the NaNs from the output
%determine, how many value columns are in the resulting fields (all but the
%first two)
ctcresField = 3:size(resultingField, 2);
%remove the row if all value columns contain NaNs
resultingField = removeNans(resultingField, true, ctcresField);

%determine, how many value columns are in the interpolated field (all but the
%first two)
ctcfieldTwoInt = 3:size(fieldTwoInt, 2);
%remove the row if all value columns contain NaNs
fieldTwoInt = removeNans(fieldTwoInt, true, ctcfieldTwoInt);


end

%---------------------------------------------------------
%-----End of Main Function, beginning of subfunctions-----
%---------------------------------------------------------

function  arrayWithoutNans = removeNans(arrayWithNans, varargin)
%
%arrayWithoutNans = removeNans(arrayWithNans)
%Removes the row of an array in case there is a NaN in any column of that
%row. Returns the "cleaned" array.
%
%arrayWithoutNans = removeNans(arrayWithNans, true)
%Removes the row of an array in case all columns of that
%row are NaNs. Returns the "cleaned" array. Default is false.
%
%arrayWithoutNans = removeNans(arrayWithNans, true, columnsToConsider)
%Removes the row of an array in case all the columns specified by
%columnsToConsider in that row are NaNs. Returns the "cleaned" array.
%columnsToConsider is a column vector specifying the column indices.
%Default are all.
%
%by Bastian Tietjen, released March 2013 under a Simplified BSD licence.

%--------set defaults---------------------------------------------
%check for more than one optional input
numberOfVarArgs = length(varargin);
if numberOfVarArgs > 2
    error('removeNans:TooManyInputs', ...
        'just two optional inputs');
end

%set default values
optionalArgs = {false 1:size(arrayWithNans,2)};

%overwrite the defaults depending on the number of optional inputs
optionalArgs(1:numberOfVarArgs) = varargin;

%place the optionalArgs in variables
[onlyIfAllAreNaN, columnsToConsider] = optionalArgs{:};
%--------set defaults end-----------------------------------------


%total number of rows in that array
numberOfRows = size(arrayWithNans, 1);

%a counter for the index array
i = 1;
indexArray(i) = 0;

for n = 1:numberOfRows
    if ~isnan(arrayWithNans(n, columnsToConsider))
        %means in that row are no NaNs, do nothing
    elseif onlyIfAllAreNaN && (1 == mean(isnan(arrayWithNans(n, columnsToConsider))))
        %all columns that are considered contain NaNs, note the index
        indexArray(i) = n;
        i = i+1;
        
    elseif ~onlyIfAllAreNaN
        %in that row is at least one NaN, note the index
        indexArray(i) = n;
        i = i+1;
    end
end

%if i > 1 there is at least one NaN in that array
if i > 1    
    %remove the NaN rows
    arrayWithNans(indexArray, :) = [];   
end

arrayWithoutNans = arrayWithNans;

%end function
end

Contact us