Skip to content

Commit

Permalink
Updated for ensembleMetadata alpha testing
Browse files Browse the repository at this point in the history
  • Loading branch information
JonKing93 committed Nov 20, 2020
1 parent 096e243 commit 0eb1f7a
Show file tree
Hide file tree
Showing 15 changed files with 597 additions and 40 deletions.
3 changes: 3 additions & 0 deletions @dash/dash.m
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@

methods (Static)

% Analysis
dist = haversine(latlon1, latlon2);

% Misc
[names, lon, lat, coord, lev, time, run, var] = dimensionNames;
convertToV7_3(filename);
Expand Down
53 changes: 53 additions & 0 deletions @dash/haversine.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
function[dist] = haversine( latlon1, latlon2 )
%% Computes the distance between lat-lon coordinates
%
% dist = haversine( latlon )
% Computes the distance between each set of latitude-longitude coordinates
%
% dist = haversine( latlon1, latlon2 )
% Computes the distance between each coordinate listed in latlon1 and each
% coordinate listed in latlon2.
%
% ----- Inputs -----
%
% latlon: A set a latitude-longitude coordinates. A numeric matrix with two
% columns. First column is the latitude coordinates. Second column is
% the longitude coordinate.
%
% ----- Outputs -----
%
% dist: The distance between the coordinates.
%
% If you provided a single input, dist is a symmetric matrix with each
% rows and columns corresponding to the coordinates listed in latlon.
%
% If you provided two inputs, the rows of dist correspond to latlon1 and
% the columns correspond to latlon2.

% Default for the second set of coordinates
if ~exist('latlon2','var') || isempty(latlon2)
latlon2 = latlon1;
end

% Radius of the Earth
R = 6378.137;

% Convert to radians
latlon1 = latlon1 * pi/180;
latlon2 = latlon2 * pi/180;

% Transpose latlon2 for singleton expansion
latlon2 = latlon2';

% Get the change in lat and lon
dLat = latlon1(:,1) - latlon2(1,:);
dLon = latlon1(:,2) - latlon2(2,:);

% Get haversine function of the central angle
a = sin(dLat/2).^2 + ( cos(latlon1(:,1)) .* cos(latlon2(1,:)) .* sin(dLon/2).^2);
c = 2 * atan2( sqrt(a), sqrt(1-a) );

% Get the distance
dist = R * c;

end
54 changes: 54 additions & 0 deletions @ensembleMetadata/closestLatLon.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
function[rows] = closestLatLon(obj, latlon, varName, verbose)
%% Returns the state vector rows closest to a set of lat-lon coordinates
%
% rows = obj.closestLatLon( coordinate )
% Returns the state vector rows closest to the given coordinate.
%
% rows = obj.closestLatLon( coordinate, varName )
% Returns the state vector rows that are closest to the given coordinate
% for a particular variable.
%
% rows = obj.closestLatLon( coordinate, varName, verbose )
% Optionally disable console messages.
%
% ----- Inputs -----
%
% coordinate: A latitude-longitude coordinate. A vector with two elements.
% The first element is the latitude coordinate and the second element is
% the longitude coordinate.
%
% varName: The name of a variable in the state vector ensemble. A string.
%
% verbose: A scalar logical that indicates whether to return console
% messages when determining coordinates (true -- default) or not (false)
%
% ----- Outputs -----
%
% rows: The rows of the state vector that are closest to the selected
% lat-lon coordinate.

% Defaults
if ~exist('varName','var') || isempty(varName)
varName = [];
end
if ~exist('verbose','var') || isempty(verbose)
verbose = [];
end

% Error check the user-specified coordinate
assert( isnumeric(latlon) & isvector(latlon), 'latlon must be a numeric vector.');
assert(numel(latlon)==2, 'latlon must have two elements.');
dash.assertRealDefined(latlon, 'latlon');
assert(abs(latlon(1))<=90, 'latitude coordinates must be between -90 and 90.');

% Get the state vector lat-lon coordinates and get the distance to each
svLatLon = obj.latlon(varName, verbose);
dist = dash.haversine(svLatLon, latlon);

% Find the state vector rows associated with the minimum distances
rows = find(dist==min(dist));
if ~isempty(varName)
rows = obj.findRows(varName, rows);
end

end
96 changes: 96 additions & 0 deletions @ensembleMetadata/columns.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
function[meta] = columns(obj, cols, varNames, dims, alwaysStruct)
%% Returns the metadata at a particular column across the ensemble.
%
% metaStruct = obj.columns( cols )
% Returns a structure with the metadata at the specified ensemble members
% for each variable and dimension in the state vector ensemble.
%
% metaStruct = obj.columns( cols, varNames )
% Returns metadata for the specified variables for all dimensions.
%
% metaStruct = obj.columns( cols, varNames, dimNames )
% Returns metadata for the specified variables and dimensions.
%
% metaStruct = obj.columns( cols, varNames, dimCell )
% Specify different dimensions for different variables.
%
% meta = obj.columns( cols, varName, dimName )
% Return metadata for a single variable and single dimension directly as an
% array.
%
% metaStruct = obj.columns( cols, varName, dimName, alwaysStruct )
% Specify to always return output as a structure.
%
% ----- Inputs -----
%
% cols: The indices of the columns (ensemble members) for which to return
% metadata. Either a vector of linear indices, or a logical vector. If a
% logical vector, must have one element per ensemble member.
%
% varNames: A list of variables in the state vector ensemble. A string
% vector or cellstring vector.
%
% dimName: A list of dimension names. A string vector or cellstring vector.
%
% dimCell: A cell vector with one element per listed dimension name. Each
% element contains a list of dimension names for the corresponding
% variable.
%
% alwaysStruct: A scalar logical that indicates if metadata should always
% be returned as a structure (true) or not (false -- default)
%
% ----- Outputs -----
%
% metaStruct: A structure holding metadata at the specified column for the
% variables and dimensions.
%
% meta: An array with metadata for the specified variable and dimension.
% Has one row per specified ensemble member.

% Error check the columns
dash.assertVectorTypeN(cols, 'numeric', [], 'cols');
cols = dash.checkIndices(cols, 'cols', obj.nEns, 'the number of ensemble members');

% Default variable names. Error check. Indices
if ~exist('varNames','var') || isempty(varNames)
varNames = obj.variableNames;
end
varNames = dash.assertStrList(varNames, 'varNames');
v = dash.checkStrsInList(varNames, obj.variableNames, 'varNames', 'variables in the state vector');
nVars = numel(v);

% Default dimension names. Error check. Propagate strings into cells
if ~exist('dims','var') || isempty(dims)
dims = obj.dims(v);
elseif ~iscell(dims)
dims = dash.assertStrList(dims, 'dims');
dims = repmat({dims}, [nVars,1]);
else
for d = 1:numel(dims)
dims{d} = dash.assertStrList(dims{d}, sprintf('Element %.f of dimCell', d));
end
end
dash.assertVectorTypeN(dims, 'cell', nVars, 'dims');

% Default and error check alwaysStruct
if ~exist('alwaysStruct','var') || isempty(alwaysStruct)
alwaysStruct = false;
end
dash.assertScalarType(alwaysStruct, 'alwaysStruct', 'logical', 'logical');

% Initialize the output structure
meta = struct();

% Get the metadata for each variable
for k = 1:nVars
var = varNames(k);
indices = repmat({cols}, [1, numel(dims{k})]);
meta.(var) = obj.variable(var, dims{k}, 'ensemble', indices, true);
end

% Optionally return array
if ~alwaysStruct && nVars==1 && numel(dims{1})==1
meta = meta.(var).(dims{1});
end

end
9 changes: 7 additions & 2 deletions @ensembleMetadata/ensembleMetadata.m
Original file line number Diff line number Diff line change
Expand Up @@ -163,9 +163,14 @@
obj = rename(obj, newName);

[V, meta] = regrid(obj, X, varName, dimOrder, d, keepSingletons);
meta = variable(obj, varName, dims, type, indices);

meta = variable(obj, varName, dims, type, indices, alwaysStruct);
meta = dimension(obj, dim, alwaysStruct);
[latlon] = coordinates(obj, dim, verbose);
meta = rows(obj, rows, dims, fullStruct);
meta = columns(obj, cols, varNames, dims, alwaysStruct);

[latlon] = latlon(obj, varName, verbose);
rows = closestLatLon(obj, latlon, varName, verbose);
rows = findRows(obj, varName, varRows);
[nState, nEns] = sizes(obj, vars);

Expand Down
Loading

0 comments on commit 0eb1f7a

Please sign in to comment.