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

Prep for v1 release #6

Closed
wants to merge 73 commits into from
Closed

Prep for v1 release #6

wants to merge 73 commits into from

Conversation

sray014
Copy link
Collaborator

@sray014 sray014 commented Jan 29, 2025

This PR makes several improvements to hecstac, specifically the RAS module by:

  • Fixing 2d geometry handling so that it properly reads mesh areas from geometry hdf files if they exist within the file.
  • Handle the coordinate reference systems correctly including situations where one is provided or when it can be extracted from the geom hdf file.
  • Adding needed handling to check if a geom hdf has 2d geometry.
  • Adding handling for retrieving the mesh areas for different crs situations.
  • Updating thumbnail creation to work with new crs handling.
  • Cleaning code that is not needed/unused.
  • Fixing item asset href's.

@sray014 sray014 requested a review from thwllms January 29, 2025 22:18
@thwllms
Copy link

thwllms commented Jan 30, 2025

rashdf needs to be added to pyproject.toml

Edit: it seems like boto3 is an undeclared dependency as well? Wasn't expecting to need that for generating a RAS Item locally.

Also boto3-stubs[s3] and contextily.

@thwllms
Copy link

thwllms commented Jan 30, 2025

I tried generating a RAS Item with the Muncie model from the RAS 6.6 example projects and ran into an issue with a missing CRS... maybe this is okay if we consider the Muncie model to be an outlier for our immediate purposes?

>>> RASModelItem("/mnt/c/temp/Example_Projects_6_6/2D Unsteady Flow Hydraulics/Muncie/Muncie.prj", "asdf")
WARNING:root:Unable to parse project version
WARNING:root:Could not extract crs from /mnt/c/temp/Example_Projects_6_6/2D Unsteady Flow Hydraulics/Muncie/Muncie.g01.hdf
WARNING:root:No reference lines found.
WARNING:root:No mesh areas found for /mnt/c/temp/Example_Projects_6_6/2D Unsteady Flow Hydraulics/Muncie/Muncie.g01.hdf
WARNING:root:Could not extract crs from /mnt/c/temp/Example_Projects_6_6/2D Unsteady Flow Hydraulics/Muncie/Muncie.g02.hdf
WARNING:root:No reference lines found.
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/thomaswilliams/dev/hecstac/hecstac/ras/item.py", line 83, in __init__
    self.add_ras_asset(fpath)
  File "/home/thomaswilliams/dev/hecstac/hecstac/ras/item.py", line 202, in add_ras_asset
    if asset.check_2d:
       ^^^^^^^^^^^^^^
  File "/home/thomaswilliams/dev/hecstac/hecstac/ras/assets.py", line 382, in check_2d
    if self.hdf_object.mesh_areas(self.crs):
       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/thomaswilliams/dev/hecstac/hecstac/ras/parser.py", line 1166, in mesh_areas
    raise CRSError("Mesh areas have no CRS and have none to be set to")
pyproj.exceptions.CRSError: Mesh areas have no CRS and have none to be set to

Edit: per discussion on 30 Jan call, CRS needs to be provided for Muncie.

@thwllms
Copy link

thwllms commented Jan 30, 2025

@sray014 I downloaded a Duwamish HMS model from USACE Model Library and tried to create an Item; got this... any ideas?

>>> HMSModelItem("/mnt/c/temp/duwamish/Duwamish_SST.hms", "asdf")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/thomaswilliams/dev/hecstac/hecstac/hms/item.py", line 48, in __init__
    self.pf = ProjectFile(self.hms_project_file, assert_uniform_version=False)
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/thomaswilliams/dev/hecstac/hecstac/hms/parser.py", line 115, in __init__
    self.scan_for_terrain_run_grid_gage_pdata()
  File "/home/thomaswilliams/dev/hecstac/hecstac/hms/parser.py", line 139, in scan_for_terrain_run_grid_gage_pdata
    self.terrain = TerrainFile(path)
                   ^^^^^^^^^^^^^^^^^
  File "/home/thomaswilliams/dev/hecstac/hecstac/hms/parser.py", line 725, in __init__
    super().__init__(path, client=client, bucket=bucket)
  File "/home/thomaswilliams/dev/hecstac/hecstac/hms/parser.py", line 56, in __init__
    self.read_content()
  File "/home/thomaswilliams/dev/hecstac/hecstac/hms/parser.py", line 62, in read_content
    self.content = f.read()
                   ^^^^^^^^
  File "<frozen codecs>", line 322, in decode
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xb2 in position 242: invalid start byte

Edit: it seems like the problem is that the HMS Terrain file encoding is latin1 (according to Vim, anyway)? 😵 I've literally never seen that before. No clue if that's an HMS thing, a Model Library thing, or what. This works:

>>> with open("/mnt/c/temp/duwamish/Duwamish_SST.terrain", "r", encoding="latin1") as f:
...     f.read()
...
'Terrain Data Manager: Duwamish SST\n     Version: 4.12\n     Filepath Separator: \\\nEnd:\n\nTerrain Data: Duwamish_10M\n     Description: \n     Terrain Directory: terrain\\Duwamish_10M\n     Vertical Units: Feet\n     Stream Threshold: 1.5 mi²\n     Last Modified Date: 7 November 2023\n     Last Modified Time: 02:17:44\nEnd:\n'

Edit (again): it seems like cp1252 might be the correct encoding after doing some research. I made a small tweak to try to get around this...

diff --git a/hecstac/hms/parser.py b/hecstac/hms/parser.py
index 2762be3..e7bb31e 100644
--- a/hecstac/hms/parser.py
+++ b/hecstac/hms/parser.py
@@ -58,8 +58,12 @@ class BaseTextFile(ABC):

     def read_content(self):
         if os.path.exists(self.path):
-            with open(self.path) as f:
-                self.content = f.read()
+            try:
+                with open(self.path) as f:
+                    self.content = f.read()
+            except UnicodeDecodeError as e:
+                with open(self.path, encoding="cp1252") as f:
+                    self.content = f.read()
         else:
             try:
                 response = self.client.get_object(Bucket=self.bucket, Key=self.path)

...but ran into a different error?

>>> HMSModelItem("/mnt/c/temp/duwamish/Duwamish_SST.hms", "asdf")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/thomaswilliams/dev/hecstac/hecstac/hms/item.py", line 53, in __init__
    self._geometry,
    ^^^^^^^^^^^^^^
  File "/home/thomaswilliams/dev/hecstac/hecstac/hms/item.py", line 106, in _geometry
    geometries = [b.basin_geom.simplify(0.001) for b in self.pf.basins]
                  ^^^^^^^^^^^^
  File "/home/thomaswilliams/dev/hecstac/hecstac/hms/parser.py", line 490, in basin_geom
    return utils.remove_holes(self.feature_2_gdf("Subbasin").make_valid().to_crs(4326).union_all())
                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/thomaswilliams/dev/hecstac/hecstac/hms/parser.py", line 497, in feature_2_gdf
    for e in self.elements.get_element_type(element_type):
             ^^^^^^^^^^^^^
  File "/home/thomaswilliams/dev/hecstac/hecstac/hms/parser.py", line 367, in elements
    sqlite = SqliteDB(
             ^^^^^^^^^
  File "/home/thomaswilliams/dev/hecstac/hecstac/hms/parser.py", line 864, in __init__
    self.subbasin_feats = gpd.read_file(self.path, layer="subbasin2d", engine=GPD_WRITE_ENGINE)
                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/thomaswilliams/dev/hecstac/venv-hecstac/lib/python3.12/site-packages/geopandas/io/file.py", line 306, in _read_file
    return _read_file_fiona(
           ^^^^^^^^^^^^^^^^^
  File "/home/thomaswilliams/dev/hecstac/venv-hecstac/lib/python3.12/site-packages/geopandas/io/file.py", line 418, in _read_file_fiona
    df = GeoDataFrame.from_features(
         ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/thomaswilliams/dev/hecstac/venv-hecstac/lib/python3.12/site-packages/geopandas/geodataframe.py", line 737, in from_features
    "geometry": shape(feature["geometry"]) if feature["geometry"] else None
                ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/thomaswilliams/dev/hecstac/venv-hecstac/lib/python3.12/site-packages/shapely/geometry/geo.py", line 107, in shape
    return MultiPolygon([[c[0], c[1:]] for c in ob["coordinates"]])
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/thomaswilliams/dev/hecstac/venv-hecstac/lib/python3.12/site-packages/shapely/geometry/multipolygon.py", line 89, in __new__
    return shapely.multipolygons(subs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/thomaswilliams/dev/hecstac/venv-hecstac/lib/python3.12/site-packages/shapely/decorators.py", line 77, in wrapped
    return func(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^
  File "/home/thomaswilliams/dev/hecstac/venv-hecstac/lib/python3.12/site-packages/shapely/creation.py", line 429, in multipolygons
    return lib.create_collection(geometries, typ, out=out, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
TypeError: ufunc 'create_collection' not supported for the input types, and the inputs could not be safely coerced to any supported types according to the casting rule ''safe''

@thwllms
Copy link

thwllms commented Jan 30, 2025

@sray014 I think I've thrown a lot at you so I'll pause and let you respond to the comments so far. I could very easily be doing something weird on my end. Let me know.

@sray014
Copy link
Collaborator Author

sray014 commented Jan 30, 2025

@thwllms The HMS Item creation is more @mdeshotel area of expertise. Might be better to make an issue on that with the HMS item and focus on ras items for this PR. What do you think @slawler ?

@sclaw
Copy link
Collaborator

sclaw commented Feb 3, 2025

I added a review in #11. Let me know if you have any questions.

@sray014 sray014 closed this Feb 10, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants