Skip to content

Commit

Permalink
Merge pull request #311 from podaac/release/2.13.0
Browse files Browse the repository at this point in the history
Release 2.13.0
  • Loading branch information
jamesfwood authored Jan 6, 2025
2 parents d3f0a0d + a3224fb commit a60d2b8
Show file tree
Hide file tree
Showing 13 changed files with 1,296 additions and 812 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/build-pipeline.yml
Original file line number Diff line number Diff line change
Expand Up @@ -315,7 +315,7 @@ jobs:
uses: softprops/action-gh-release@v2
with:
tag_name: "${{ env.software_version }}" # Use the tag that triggered the action
release_name: Release v{{ env.software_version }}
name: Release v{{ env.software_version }}
draft: false
generate_release_notes: true
token: ${{ secrets.GITHUB_TOKEN }}
12 changes: 12 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,18 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Security


## [2.13.0]
### Added
### Changed
### Deprecated
### Removed
- Removed the "time" dependency when doing spatial only subsetting.
### Fixed
- Updated xarray enhancement get_indexers_from_nd function for SMAP_RSS_L2_SSS_V6.
- Fix minor bug in checking for empty indexers and same data bounds.
### Security


## [2.12.0]
### Added
- Added custom exception to progate error messages to harmony.
Expand Down
7 changes: 2 additions & 5 deletions deployment/harmony_deploy.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,9 +59,6 @@ def bearer_token() -> str:
}

response = requests.put(url, headers=headers, json=data)
response.raise_for_status()

print(response.status_code)
try:
print(response.json())
except json.JSONDecodeError:
print("Response content is not in JSON format")
print(f"Response JSON: {response.json()}")
4 changes: 2 additions & 2 deletions docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,7 @@
'sphinx.ext.coverage',
'sphinx.ext.viewcode',
'sphinx.ext.napoleon',
'sphinx_rtd_theme',
'm2r2'
'sphinx_rtd_theme'
]

# Add any paths that contain templates here, relative to this directory.
Expand Down Expand Up @@ -77,3 +76,4 @@
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ['_static']

9 changes: 4 additions & 5 deletions podaac/subsetter/subset.py
Original file line number Diff line number Diff line change
Expand Up @@ -560,11 +560,7 @@ def compute_time_variable_name(dataset: xr.Dataset, lat_var: xr.Variable, total_
if var_name not in total_time_vars and 'time' in var_name_time.lower() and dataset[var_name].squeeze().dims[0] in lat_var.squeeze().dims:
return var_name

# OB.DAAC data does not have a time variable. Returning the following field of a composite time value to avoid exceptions.
if '__scan_line_attributes__day' in dataset.data_vars:
return '__scan_line_attributes__day'

raise ValueError('Unable to determine time variable')
return None


def compute_utc_name(dataset: xr.Dataset) -> Union[str, None]:
Expand Down Expand Up @@ -1296,6 +1292,9 @@ def subset(file_to_subset: str, bbox: np.ndarray, output_file: str,
time_var_names=time_var_names
)

if not time_var_names and (min_time or max_time):
raise ValueError('Could not determine time variable')

start_date = None
if hdf_type and (min_time or max_time):
dataset, start_date = tc.convert_to_datetime(dataset, time_var_names, hdf_type)
Expand Down
18 changes: 15 additions & 3 deletions podaac/subsetter/subset_harmony.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
from tempfile import mkdtemp
import traceback
from typing import List, Union
import sys

import pystac
from pystac import Asset
Expand All @@ -41,9 +42,16 @@


class L2SSException(HarmonyException):
"""Base class for exceptions in the Harmony GDAL Adapter."""

"""L2SS Exception class for custom error messages to see in harmony api calls."""
def __init__(self, original_exception):
# Ensure we can extract traceback information
if original_exception.__traceback__ is None:
# Capture the current traceback if not already present
try:
raise original_exception
except type(original_exception):
original_exception.__traceback__ = sys.exc_info()[2]

# Extract the last traceback entry (most recent call) for the error location
tb = traceback.extract_tb(original_exception.__traceback__)[-1]

Expand All @@ -57,7 +65,11 @@ def __init__(self, original_exception):
readable_message = (f"Error in file '{filename}', line {lineno}, in function '{funcname}': "
f"{error_msg}")

super().__init__(readable_message, 'nasa/harmony-gdal-adapter')
# Call the parent class constructor with the formatted message and category
super().__init__(readable_message, 'podaac/l2-subsetter')

# Store the original exception for potential further investigation
self.original_exception = original_exception


def podaac_to_harmony_bbox(bbox: np.ndarray) -> Union[np.ndarray, float]:
Expand Down
77 changes: 35 additions & 42 deletions podaac/subsetter/xarray_enhancements.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,57 +69,50 @@ def get_indexers_from_nd(cond: xr.Dataset, cut: bool) -> dict:
Indexer dictionary for the provided condition.
"""
# check if the lat/lon coordinate numpy array has 2 or more dimensions
transpose = False
if cond.values.squeeze().ndim == 2:
x_axis = 1
y_axis = 0
transpose = dim_grid = False
ndim = cond.values.squeeze().ndim

# Determine axes and flags
if ndim == 2:
x_axis, y_axis = 1, 0
else:
if any('xtrack' in dim for dim in list(cond.dims)) and\
any('atrack' in dim for dim in list(cond.dims)):
x_axis = list(cond.dims).index('xtrack')
y_axis = list(cond.dims).index('atrack')
if 'xtrack' in cond.dims and 'atrack' in cond.dims:
x_axis, y_axis = cond.dims.index('xtrack'), cond.dims.index('atrack')
transpose = True
elif 'xdim_grid' in cond.dims and 'ydim_grid' in cond.dims:
x_axis, y_axis = cond.dims.index('xdim_grid'), cond.dims.index('ydim_grid')
dim_grid = x_axis == 1 and y_axis == 0
else:
x_axis = 2
y_axis = 1
x_axis, y_axis = 2, 1

rows = np.any(cond.values.squeeze(), axis=x_axis)
if cut:
cols = np.any(cond.values.squeeze(), axis=y_axis)
else:
cols = np.ones(len(cond.values[0]))
# Compute rows and columns
squeezed_values = cond.values.squeeze()
rows = np.any(squeezed_values, axis=x_axis)
cols = np.any(squeezed_values, axis=y_axis) if cut else np.ones(len(squeezed_values[0]))

# If the subsetted area is equal to the original area
if np.all(rows) & np.all(cols):
# Log information about subsetted area
if np.all(rows) and np.all(cols):
logging.info("Subsetted area equal to the original granule.")

# If the subsetted area is empty
if not np.any(rows) | np.any(cols):
if not np.any(rows) or not np.any(cols):
logging.info("No data within the given bounding box.")

cond_shape_list = list(cond.shape)
cond_list = list(cond.dims)
output = [idx for idx, element in enumerate(cond_shape_list) if element == 1]
for i in output:
cond_list.pop(i)

if rows.ndim == 1:
indexers = {
cond_list[0]: np.where(rows)[0],
cond_list[1]: np.where(cols)[0]
}
else:
# if the lat/lon had 3 dimensions the conditional array was identical in the z direction - taking the first
# Determine dimensions and clean them up
cond_dims = list(cond.dims)
cond_shape = list(cond.shape)
cond_dims = [dim for dim, size in zip(cond_dims, cond_shape) if size > 1]

# Adjust for 3D data
if rows.ndim > 1:
if transpose:
rows = rows.transpose()[0]
cols = cols.transpose()[0]
else:
rows = rows[0]
cols = cols[0]
indexers = {
cond_list[y_axis]: np.where(rows)[0],
cond_list[x_axis]: np.where(cols)[0]
}
rows, cols = rows.transpose()[0], cols.transpose()[0]
elif not dim_grid:
rows, cols = rows[0], cols[0]

# Generate indexers
indexers = {
cond_dims[y_axis]: np.where(rows)[0],
cond_dims[x_axis]: np.where(cols)[0]
}

return indexers

Expand Down
Loading

0 comments on commit a60d2b8

Please sign in to comment.