Skip to content

Commit

Permalink
Per #1055, ci-run-unit, parse rotated lat/lon grids from CF-compliant…
Browse files Browse the repository at this point in the history
… NetCDF files.
  • Loading branch information
JohnHalleyGotway committed Feb 4, 2022
1 parent 7c18231 commit d8a705c
Show file tree
Hide file tree
Showing 2 changed files with 202 additions and 11 deletions.
210 changes: 199 additions & 11 deletions met/src/libcode/vx_data2d_nccf/nccf_file.cc
Original file line number Diff line number Diff line change
Expand Up @@ -179,8 +179,8 @@ bool NcCfFile::open(const char * filepath)
// calling program. In the case of this example, we just exit with
// an NC_ERR error code.

//FIXME: Commented out with NetcDf4 enabling
//NcError err(NcError::silent_nonfatal);
// FIXME: Commented out with NetCDF4 enabling
// NcError err(NcError::silent_nonfatal);

// Open the file

Expand Down Expand Up @@ -2266,16 +2266,190 @@ void NcCfFile::get_grid_mapping_polar_stereographic(const NcVar *grid_mapping_va
}


////////////////////////////////////////////////////////////////////////
//
// Reference:
// https://cfconventions.org/Data/cf-conventions/cf-conventions-1.9/cf-conventions.html#_rotated_pole
//
////////////////////////////////////////////////////////////////////////


void NcCfFile::get_grid_mapping_rotated_latitude_longitude(const NcVar *grid_mapping_var)
{
static const string method_name = "NcCfFile::get_grid_mapping_rotated_latitude_longitude()";

mlog << Error << "\n" << method_name << " -> "
<< "Rotated latitude longitude grid not handled in MET.\n\n";
exit(1);
// grid_north_pole_latitude

NcVarAtt *grid_np_lat_att = get_nc_att(
grid_mapping_var, (string)"grid_north_pole_latitude");
if (IS_INVALID_NC_P(grid_np_lat_att))
{
mlog << Error << "\n" << method_name << " -> "
<< "Cannot get grid_north_pole_latitude attribute from "
<< GET_NC_NAME_P(grid_mapping_var) << " variable.\n\n";
exit(1);
}

// grid_north_pole_longitude

NcVarAtt *grid_np_lon_att = get_nc_att(
grid_mapping_var, (string)"grid_north_pole_longitude");
if (IS_INVALID_NC_P(grid_np_lon_att))
{
mlog << Error << "\n" << method_name << " -> "
<< "Cannot get grid_north_pole_longitude attribute from "
<< GET_NC_NAME_P(grid_mapping_var) << " variable.\n\n";
exit(1);
}

// Look for the grid_latitude and grid_longitude dimensions

for (int dim_num = 0; dim_num < _numDims; ++dim_num)
{
// These dimensions are identified by the standard_name attribute

const NcVar coord_var = get_var(_ncFile, _dims[dim_num]->getName().c_str());
if (IS_INVALID_NC(coord_var))
continue;

const NcVarAtt *std_name_att = get_nc_att(&coord_var, (string)"standard_name");
if (IS_INVALID_NC_P(std_name_att)) {
if (std_name_att) delete std_name_att;
continue;
}

ConcatString dim_standard_name;
if (!get_att_value_chars(std_name_att, dim_standard_name)) {
if (std_name_att) delete std_name_att;
continue;
}

if (std_name_att) delete std_name_att;

// See if this is a grid_latitude or grid_longitude dimension

if (dim_standard_name == "grid_latitude")
{
if (_yDim == 0)
{
_yDim = _dims[dim_num];

y_dim_var_name = GET_NC_NAME_P(_yDim).c_str();

for (int var_num = 0; var_num < Nvars; ++var_num)
{
if ( Var[var_num].name == GET_NC_NAME_P(_yDim))
{
_yCoordVar = Var[var_num].var;
break;
}
}
}
else
{
mlog << Warning << "\n" << method_name << " -> "
<< "Found multiple variables for grid_latitude, using \""
<< GET_NC_NAME_P(_yCoordVar) << "\".\n\n";
}
}

if (dim_standard_name == "grid_longitude")
{
if (_xDim == 0)
{
_xDim = _dims[dim_num];

x_dim_var_name = GET_NC_NAME_P(_xDim).c_str();
for (int var_num = 0; var_num < Nvars; ++var_num)
{
if ( Var[var_num].name == GET_NC_NAME_P(_xDim))
{
_xCoordVar = Var[var_num].var;
break;
}
}
}
else
{
mlog << Warning << "\n" << method_name << " -> "
<< "Found multiple variables for grid_longitude, using \""
<< GET_NC_NAME_P(_xCoordVar) << "\".\n\n";
}
}

}

if (_xDim == 0)
{
mlog << Error << "\n" << method_name << " -> "
<< "Didn't find X dimension (degrees_east) in netCDF file.\n\n";
exit(1);
}

if (_yDim == 0)
{
mlog << Error << "\n" << method_name << " -> "
<< "Didn't find Y dimension (degrees_north) in netCDF file.\n\n";
exit(1);
}

if (_xCoordVar == 0)
{
mlog << Error << "\n" << method_name << " -> "
<< "Didn't find X coord variable (" << GET_NC_NAME_P(_xDim)
<< ") in netCDF file.\n\n";
exit(1);
}

if (_yCoordVar == 0)
{
mlog << Error << "\n" << method_name << " -> "
<< "Didn't find Y coord variable (" << GET_NC_NAME_P(_yDim)
<< ") in netCDF file.\n\n";
exit(1);
}

long lon_counts = _xDim->getSize();
long lat_counts = _yDim->getSize();
if (get_data_size(_xCoordVar) != lon_counts ||
get_data_size(_yCoordVar) != lat_counts)
{
mlog << Error << "\n" << method_name << " -> "
<< "Coordinate variables don't match dimension sizes in netCDF file.\n\n";
exit(1);
}

LatLonData ll_data;

ll_data = get_data_from_lat_lon_vars(_yCoordVar, _xCoordVar, lat_counts, lon_counts);

// Fill in the Rotated LatLon data structure.

RotatedLatLonData data;

data.name = rotated_latlon_proj_type;

// Derive south pole location from the north pole
data.true_lat_south_pole = -1.0 * get_att_value_double(grid_np_lat_att);
double np_lon = rescale_lon(get_att_value_double(grid_np_lon_att));
data.true_lon_south_pole = rescale_lon(-1.0 * (180.0 - fabs(np_lon)));

// Copied from the LatLon data structure
data.rot_lat_ll = ll_data.lat_ll;
data.rot_lon_ll = ll_data.lon_ll;
data.delta_rot_lat = ll_data.delta_lat;
data.delta_rot_lon = ll_data.delta_lon;

// Grid dimension
data.Nlon = _xDim->getSize();
data.Nlat = _yDim->getSize();

data.aux_rotation = 0;

grid.set(data);

if(grid_np_lat_att) delete grid_np_lat_att;
if(grid_np_lon_att) delete grid_np_lon_att;
}


Expand Down Expand Up @@ -2865,17 +3039,31 @@ bool NcCfFile::get_grid_from_dimensions()

////////////////////////////////////////////////////////////////////////


void NcCfFile::get_grid_from_lat_lon_vars(NcVar *lat_var, NcVar *lon_var,
const long lat_counts, const long lon_counts) {
static const string method_name = "NcCfFile::get_grid_from_lat_lon_vars()";

LatLonData data = get_data_from_lat_lon_vars(lat_var, lon_var, lat_counts, lon_counts);
grid.set(data); // resets swap_to_north to false
if (data.delta_lat < 0) grid.set_swap_to_north(true);
}


////////////////////////////////////////////////////////////////////////


LatLonData NcCfFile::get_data_from_lat_lon_vars(NcVar *lat_var, NcVar *lon_var,
const long lat_counts, const long lon_counts) {
static const string method_name = "get_data_from_lat_lon_vars()";

// Figure out the dlat/dlon values from the dimension variables

long x_size = get_data_size(lon_var);
long y_size = get_data_size(lat_var);
long latlon_counts = lon_counts*lat_counts;
bool two_dim_corrd = (x_size == latlon_counts) && (y_size == latlon_counts );
if( !two_dim_corrd && (x_size != lon_counts || y_size != lat_counts))
bool two_dim_coord = (x_size == latlon_counts) && (y_size == latlon_counts );
if( !two_dim_coord && (x_size != lon_counts || y_size != lat_counts))
{
mlog << Error << "\n" << method_name << " -> "
<< "Coordinate variables don't match dimension sizes in netCDF file.\n\n";
Expand All @@ -2885,7 +3073,7 @@ void NcCfFile::get_grid_from_lat_lon_vars(NcVar *lat_var, NcVar *lon_var,
double lat_values[lat_counts];
double lon_values[lon_counts];
bool lat_first = false;
if (two_dim_corrd) {
if (two_dim_coord) {
lat_first = (lat_counts == get_dim_size(lat_var, 0));
long cur[2], length[2];
cur[0] = cur[1] = 0;
Expand Down Expand Up @@ -2992,7 +3180,7 @@ void NcCfFile::get_grid_from_lat_lon_vars(NcVar *lat_var, NcVar *lon_var,

data.name = latlon_proj_type;
data.lat_ll = lat_values[0];
data.lon_ll = -lon_values[0];
data.lon_ll = rescale_lon(-lon_values[0]);
data.delta_lat = dlat;
data.delta_lon = dlon;
data.Nlat = lat_counts;
Expand All @@ -3002,9 +3190,9 @@ void NcCfFile::get_grid_from_lat_lon_vars(NcVar *lat_var, NcVar *lon_var,
data.lat_ll = lat_values[lat_counts-1];
}

grid.set(data); // resets swap_to_north to false
if (dlat < 0) grid.set_swap_to_north(true);
return(data);

}


////////////////////////////////////////////////////////////////////////
3 changes: 3 additions & 0 deletions met/src/libcode/vx_data2d_nccf/nccf_file.h
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,9 @@ class NcCfFile {
bool get_grid_from_dimensions();
void get_grid_from_lat_lon_vars(NcVar *lat_var, NcVar *lon_var,
const long lat_counts, const long lon_counts);

LatLonData get_data_from_lat_lon_vars(NcVar *lat_var, NcVar *lon_var,
const long lat_counts, const long lon_counts);
};


Expand Down

0 comments on commit d8a705c

Please sign in to comment.