Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DAS-2300 - provides spatial subsetting support for 3d variables in SPL3SMP #30

Merged
merged 5 commits into from
Feb 18, 2025
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
## v1.1.5
### 2025-02-14

This version of HOSS adds support for 3D variables which
do not have the nominal order. This would provide support
for the 3D variables in SMAP - SPL3SMP with dimension order
information provided in the configurations file.

## v1.1.4
### 2025-02-12

Expand Down
2 changes: 1 addition & 1 deletion docker/service_version.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1.1.4
1.1.5
57 changes: 45 additions & 12 deletions hoss/coordinate_utilities.py
Original file line number Diff line number Diff line change
Expand Up @@ -136,8 +136,8 @@ def create_spatial_dimension_names_from_coordinates(

if variable is not None:
dimension_array_names = [
f'{variable.group_path}/dim_y',
f'{variable.group_path}/dim_x',
f'{variable.group_path}/y_dim',
f'{variable.group_path}/x_dim',
]
else:
raise MissingVariable(variable_name)
Expand All @@ -150,7 +150,8 @@ def create_dimension_arrays_from_coordinates(
latitude_coordinate: VariableFromDmr,
longitude_coordinate: VariableFromDmr,
crs: CRS,
projected_dimension_names: list[str],
variable_name: str,
varinfo: VarInfoFromDmr,
) -> dict[str, np.ndarray]:
"""Generate artificial 1D dimensions scales for each
2D dimension or coordinate variable.
Expand All @@ -159,8 +160,12 @@ def create_dimension_arrays_from_coordinates(
3) Generate the x-y dimscale array and return to the calling method

"""
if len(projected_dimension_names) < 2:
raise InvalidDimensionNames(projected_dimension_names)
dimension_names = get_dimension_array_names(varinfo, variable_name)
if len(dimension_names) < 2:
raise InvalidDimensionNames(dimension_names)

# check if the dimension names are configured in hoss_config
dimension_name_order = get_configured_dimension_order(varinfo, dimension_names)

lat_arr = get_2d_coordinate_array(
prefetch_dataset,
Expand All @@ -171,10 +176,12 @@ def create_dimension_arrays_from_coordinates(
longitude_coordinate.full_name_path,
)

# get the max spread x and y indices
row_indices, col_indices = get_valid_sample_pts(
lat_arr, lon_arr, latitude_coordinate, longitude_coordinate
)

# get the dimension order from the coordinate data
dim_order_is_y_x, row_dim_values = get_dimension_order_and_dim_values(
lat_arr, lon_arr, row_indices, crs, is_row=True
)
Expand All @@ -188,26 +195,48 @@ def create_dimension_arrays_from_coordinates(
lat_arr, lon_arr, dim_order_is_y_x
)

# calculate the dimension values
y_dim = interpolate_dim_values_from_sample_pts(
row_dim_values, np.transpose(row_indices)[0], row_size
)

x_dim = interpolate_dim_values_from_sample_pts(
col_dim_values, np.transpose(col_indices)[1], col_size
)

projected_y, projected_x = (
projected_dimension_names[-2],
projected_dimension_names[-1],
)

# if it is not configured in the hoss_config.json
# assume it is nominal order [z,y,x],
if not dimension_name_order:
projected_y, projected_x = dimension_names[-2:]
else:
# if it is confgured e.g. [y,x,z] order
projected_y, projected_x = (
dimension_name_order['projection_y_coordinate'],
dimension_name_order['projection_x_coordinate'],
)
if dim_order_is_y_x:
return {projected_y: y_dim, projected_x: x_dim}
raise UnsupportedDimensionOrder('x,y')
# this is not currently supported in the calling function in spatial.py
# return {projected_x: x_dim, projected_y: y_dim}


def get_configured_dimension_order(
varinfo: VarInfoFromDmr, dimension_names: list[str]
) -> dict[str, str]:
"""This function returns the dimension order in a dictionary
with standard_names that is used to define the dimensions e.g.
'projection_x_coordinate' and 'projection_y_coordinate' if they
are configured in hoss_config.json

"""
dimension_name_order = {}
for dimension_name in dimension_names:
attrs = varinfo.get_missing_variable_attributes(dimension_name)
if 'standard_name' in attrs.keys():
dimension_name_order[attrs['standard_name']] = dimension_name
return dimension_name_order


def get_2d_coordinate_array(
prefetch_dataset: Dataset,
coordinate_name: str,
Expand Down Expand Up @@ -445,10 +474,14 @@ def interpolate_dim_values_from_sample_pts(
def create_dimension_arrays_from_geotransform(
prefetch_dataset: Dataset,
latitude_coordinate: VariableFromDmr,
projected_dimension_names: list[str],
variable_name: str,
varinfo: VarInfoFromDmr,
geotranform,
) -> dict[str, np.ndarray]:
"""Generate artificial 1D dimensions scales from geotransform"""

projected_dimension_names = get_dimension_array_names(varinfo, variable_name)

lat_arr = get_2d_coordinate_array(
prefetch_dataset,
latitude_coordinate.full_name_path,
Expand Down
64 changes: 63 additions & 1 deletion hoss/hoss_config.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"Identification": "hoss_config",
"Version": 21,
"Version": 22,
"CollectionShortNamePath": [
"/HDF5_GLOBAL/short_name",
"/NC_GLOBAL/short_name",
Expand Down Expand Up @@ -442,6 +442,68 @@
],
"_Description": "SMAP L3 data are HDF5 and without dimension settings. Overrides here define the dimensions, a useful reference name, and critically, the dimension order."
},
{
"Applicability": {
"Mission": "SMAP",
"ShortNamePath": "SPL3SMP",
"VariablePattern": ".*/x_dim"
},
"Attributes": [
{
"Name": "dimensions",
"Value": "x_dim"
},
{
"Name": "Units",
"Value": "m"
},
{
"Name": "standard_name",
"Value": "projection_x_coordinate"
}
],
"_Description": "The pseudo-dimension variable is here supplemented with variable attributes (as if it was a dimension variables) to fully specify the X dimension."
},
{
"Applicability": {
"Mission": "SMAP",
"ShortNamePath": "SPL3SMP",
"VariablePattern": ".*/y_dim"
},
"Attributes": [
{
"Name": "dimensions",
"Value": "y_dim"
},
{
"Name": "Units",
"Value": "m"
},
{
"Name": "standard_name",
"Value": "projection_y_coordinate"
}
],
"_Description": "The pseudo-dimension variable is here supplemented with variable attributes (as if it was a dimension variables) to fully specify the Y dimension."
},
{
"Applicability": {
"Mission": "SMAP",
"ShortNamePath": "SPL3SMP",
"VariablePattern": ".*/am_pm"
},
"Attributes": [
{
"Name": "dimensions",
"Value": "am_pm"
},
{
"Name": "long_name",
"Value": "AM-PM dimension of size 2, 0 => AM, 1=> PM"
}
],
"_Description": "The pseudo-dimension variable is here supplemented with variable attributes (as if it was a dimension variables) to clarify the dimension name"
},
{
"Applicability": {
"Mission": "ICESat2",
Expand Down
9 changes: 5 additions & 4 deletions hoss/spatial.py
Original file line number Diff line number Diff line change
Expand Up @@ -248,14 +248,13 @@ def get_x_y_index_ranges_from_coordinates(
"""

crs = get_variable_crs(non_spatial_variable, varinfo)

projected_dimension_names = get_dimension_array_names(varinfo, non_spatial_variable)
master_geotransform = get_master_geotransform(non_spatial_variable, varinfo)
if master_geotransform:
dimension_arrays = create_dimension_arrays_from_geotransform(
prefetch_coordinate_datasets,
latitude_coordinate,
projected_dimension_names,
non_spatial_variable,
varinfo,
master_geotransform,
)
else:
Expand All @@ -264,7 +263,9 @@ def get_x_y_index_ranges_from_coordinates(
latitude_coordinate,
longitude_coordinate,
crs,
projected_dimension_names,
# projected_dimension_names,
non_spatial_variable,
varinfo,
)

projected_y, projected_x = dimension_arrays.keys()
Expand Down
Loading