Skip to content
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