From d9991594654f2fc97d88b09cf194098d9c631869 Mon Sep 17 00:00:00 2001 From: Chang Liao Date: Wed, 10 May 2023 23:37:32 -0600 Subject: [PATCH 1/3] remove submodule --- .gitmodules | 3 --- 1 file changed, 3 deletions(-) delete mode 100644 .gitmodules diff --git a/.gitmodules b/.gitmodules deleted file mode 100644 index 5c61650..0000000 --- a/.gitmodules +++ /dev/null @@ -1,3 +0,0 @@ -[submodule "external/hexwatershed"] - path = external/hexwatershed - url = https://github.com/changliao1025/hexwatershed.git From b5bf83147779ae6f2706dd5edad4a8d4a8a8e585 Mon Sep 17 00:00:00 2001 From: changliao1025 Date: Wed, 17 May 2023 09:43:50 -0700 Subject: [PATCH 2/3] only distribute binary on pypi --- .github/workflows/python-publish.yml | 4 +- meta.yaml | 4 +- pyhexwatershed/classes/_visual.py | 21 ++--- pyhexwatershed/classes/pycase.py | 89 +++++++++++++++---- ...watershed_read_model_configuration_file.py | 78 ++++++++-------- setup.cfg | 2 +- setup.py | 21 +++-- 7 files changed, 137 insertions(+), 82 deletions(-) diff --git a/.github/workflows/python-publish.yml b/.github/workflows/python-publish.yml index 7f25d05..967f181 100644 --- a/.github/workflows/python-publish.yml +++ b/.github/workflows/python-publish.yml @@ -27,14 +27,14 @@ jobs: - name: Install dependencies run: | python -m pip install --upgrade pip - python -m pip install setuptools wheel twine + python -m pip install setuptools wheel - name: Build external package run: python setup.py build_external - name: Build source distribution run: | - python setup.py sdist bdist_wheel + python setup.py bdist_wheel - name: Publish package uses: pypa/gh-action-pypi-publish@release/v1 diff --git a/meta.yaml b/meta.yaml index df44c93..aa4ac38 100644 --- a/meta.yaml +++ b/meta.yaml @@ -1,9 +1,9 @@ package: name: "hexwatershed" - version: "0.2.23" + version: "0.2.24" source: - git_rev: v0.2.23 + git_rev: v0.2.24 git_url: https://github.com/changliao1025/pyhexwatershed build: diff --git a/pyhexwatershed/classes/_visual.py b/pyhexwatershed/classes/_visual.py index 69ac1a7..095b641 100644 --- a/pyhexwatershed/classes/_visual.py +++ b/pyhexwatershed/classes/_visual.py @@ -13,7 +13,7 @@ import matplotlib.cm as cm import matplotlib.animation as animation from matplotlib.animation import FuncAnimation -import matplotlib + mpl.use("Agg") from shapely.wkt import loads from cartopy.mpl.ticker import LongitudeFormatter, LatitudeFormatter @@ -371,6 +371,7 @@ def _plot_mesh_with_variable(self, sFilename_in, sVariable_in, aExtent_in=None, dLat_max = aLocation[k,1] if aLocation[k,1] < dLat_min: dLat_min = aLocation[k,1] + pProjection_map = ccrs.Orthographic(central_longitude = 0.50*(dLon_max+dLon_min), central_latitude = 0.50*(dLat_max+dLat_min), globe=None) fig = plt.figure( dpi=300 ) fig.set_figwidth( iFigwidth ) @@ -551,18 +552,12 @@ def _plot_flow_direction(self, sFilename_in, aExtent_in=None, iFigwidth_in=None dummy0 = loads( pGeometry_in.ExportToWkt() ) aCoords_gcs = dummy0.coords aCoords_gcs= np.array(aCoords_gcs) - nvertex = len(aCoords_gcs) - for i in range(nvertex): - dLon = aCoords_gcs[i][0] - dLat = aCoords_gcs[i][1] - if dLon > dLon_max: - dLon_max = dLon - if dLon < dLon_min: - dLon_min = dLon - if dLat > dLat_max: - dLat_max = dLat - if dLat < dLat_min: - dLat_min = dLat + aCoords_gcs = aCoords_gcs[:,0:2] + dLon_max = np.max( [dLon_max, np.max(aCoords_gcs[:,0])] ) + dLon_min = np.min( [dLon_min, np.min(aCoords_gcs[:,0])] ) + dLat_max = np.max( [dLat_max, np.max(aCoords_gcs[:,1])] ) + dLat_min = np.min( [dLat_min, np.min(aCoords_gcs[:,1])] ) + pProjection_map = ccrs.Orthographic(central_longitude = 0.50*(dLon_max+dLon_min), central_latitude = 0.50*(dLat_max+dLat_min), globe=None) fig = plt.figure( dpi=300) fig.set_figwidth( iFigwidth ) diff --git a/pyhexwatershed/classes/pycase.py b/pyhexwatershed/classes/pycase.py index 9b330df..50c136d 100644 --- a/pyhexwatershed/classes/pycase.py +++ b/pyhexwatershed/classes/pycase.py @@ -53,6 +53,7 @@ class hexwatershedcase(object): iMesh_type = 4 iFlag_save_mesh = 0 iFlag_use_mesh_dem=0 + iFlag_user_provided_binary= 0 iFlag_slurm = 0 nOutlet=1 dResolution_degree=0.0 @@ -67,6 +68,7 @@ class hexwatershedcase(object): sFilename_mesh_info='' sFilename_flowline_info='' sFilename_basins='' + sFilename_hexwatershed_bin='' sWorkspace_model_region='' sRegion='' @@ -167,6 +169,11 @@ def __init__(self, aConfig_in): if 'iFlag_elevation_profile' in aConfig_in: self.iFlag_elevation_profile = int(aConfig_in[ 'iFlag_elevation_profile']) + + if 'iFlag_user_provided_binary' in aConfig_in: + self.iFlag_user_provided_binary = int(aConfig_in[ 'iFlag_user_provided_binary']) + else: + self.iFlag_user_provided_binary = 0 if 'nOutlet' in aConfig_in: self.nOutlet = int(aConfig_in[ 'nOutlet']) @@ -191,6 +198,27 @@ def __init__(self, aConfig_in): if 'sFilename_mesh_netcdf' in aConfig_in: self.sFilename_mesh_netcdf = aConfig_in['sFilename_mesh_netcdf'] + if self.iFlag_user_provided_binary == 1: + print('The model will use the user provided binary file') + if 'sFilename_hexwatershed_bin' in aConfig_in: + self.sFilename_hexwatershed_bin = aConfig_in['sFilename_hexwatershed_bin'] + #check file exist + if not os.path.exists(self.sFilename_hexwatershed_bin): + print('The user provided binary file does not exist. The model will use the default binary file') + self.iFlag_user_provided_binary = 0 + pass + else: + print(self.sFilename_hexwatershed_bin) + + else: + print('The binray file is not provided. The model will use the default binary file') + self.iFlag_user_provided_binary = 0 + pass + else: + print('The model will use the default binary file') + pass + + if 'iCase_index' in aConfig_in: iCase_index = int(aConfig_in['iCase_index']) else: @@ -257,8 +285,6 @@ def __init__(self, aConfig_in): if 'sJob' in aConfig_in: self.sJob = aConfig_in['sJob'] - - if 'sFilename_basins' in aConfig_in: self.sFilename_basins = aConfig_in['sFilename_basins'] @@ -329,25 +355,52 @@ def setup(self): self.pPyFlowline.setup() #setup the hexwatershed system = platform.system() - # Get the distribution object for the package - distribution = pkg_resources.get_distribution('hexwatershed') - # Get the installation path for the package - sPath_installation = distribution.location - if platform.system() == 'Windows': - sFilename_executable = 'hexwatershed.exe' - sFilename_hexwatershed_bin = os.path.join(str(Path(sPath_installation + '/pyhexwatershed/_bin/') ) , sFilename_executable ) - #copy the binary file + iFlag_found_binary = 0 + + + #if user provided the binary, then use the user provided binary + if self.iFlag_user_provided_binary == 1: + sFilename_executable = 'hexwatershed' + #copy the binary + iFlag_found_binary = 1 sFilename_new = os.path.join(str(Path(self.sWorkspace_output_hexwatershed) ) , sFilename_executable ) - copy2(sFilename_hexwatershed_bin, sFilename_new) + copy2(self.sFilename_hexwatershed_bin, sFilename_new) os.chmod(sFilename_new, stat.S_IRWXU ) + pass + else: + + # Get the distribution object for the package + distribution = pkg_resources.get_distribution('hexwatershed') + # Get the installation path for the package + sPath_installation = distribution.location + + if system == 'Windows': + sFilename_executable = 'hexwatershed.exe' + else: + sFilename_executable = 'hexwatershed' + + #search for system wide binary in the system path + for folder in os.environ['PATH'].split(os.pathsep): + sFilename_hexwatershed_bin = os.path.join(folder, sFilename_executable) + if os.path.isfile(sFilename_hexwatershed_bin): + print('Found binary at:', sFilename_hexwatershed_bin) + iFlag_found_binary = 1 + break + else: + print('Binary not found in system path.') + if iFlag_found_binary ==1: + pass + else: + sFilename_hexwatershed_bin = os.path.join(str(Path(sPath_installation + '/pyhexwatershed/_bin/') ) , sFilename_executable ) + if os.path.isfile(sFilename_hexwatershed_bin): + iFlag_found_binary=1 + #copy the binary file + sFilename_new = os.path.join(str(Path(self.sWorkspace_output_hexwatershed) ) , sFilename_executable ) + copy2(sFilename_hexwatershed_bin, sFilename_new) + os.chmod(sFilename_new, stat.S_IRWXU ) + else: + iFlag_found_binary = 0 - else: - sFilename_executable = 'hexwatershed' - sFilename_hexwatershed_bin = os.path.join(str(Path(sPath_installation + '/pyhexwatershed/_bin/') ) , sFilename_executable ) - #copy the binary file - sFilename_new = os.path.join(str(Path(self.sWorkspace_output_hexwatershed) ) , sFilename_executable ) - copy2(sFilename_hexwatershed_bin, sFilename_new) - os.chmod(sFilename_new, stat.S_IRWXU ) return diff --git a/pyhexwatershed/pyhexwatershed_read_model_configuration_file.py b/pyhexwatershed/pyhexwatershed_read_model_configuration_file.py index 6c7f009..547b64c 100644 --- a/pyhexwatershed/pyhexwatershed_read_model_configuration_file.py +++ b/pyhexwatershed/pyhexwatershed_read_model_configuration_file.py @@ -1,4 +1,4 @@ -import os +import os import sys #used to add system path import datetime import json @@ -9,20 +9,20 @@ pDate = datetime.datetime.today() sDate_default = "{:04d}".format(pDate.year) + "{:02d}".format(pDate.month) + "{:02d}".format(pDate.day) -def pyhexwatershed_read_model_configuration_file(sFilename_configuration_in,\ - iCase_index_in=None, \ - iFlag_stream_burning_topology_in = None,\ - iFlag_elevation_profile_in = None,\ - iFlag_use_mesh_dem_in= None,\ - dResolution_meter_in = None,\ - sDate_in = None,\ - sMesh_type_in=None): +def pyhexwatershed_read_model_configuration_file(sFilename_configuration_in, + iCase_index_in=None, + iFlag_stream_burning_topology_in = None, + iFlag_elevation_profile_in = None, + iFlag_use_mesh_dem_in= None, + dResolution_meter_in = None, + sDate_in = None, + sMesh_type_in=None): + - # Opening JSON file with open(sFilename_configuration_in) as json_file: - aConfig = json.load(json_file) - + aConfig = json.load(json_file) + if sDate_in is not None: sDate = sDate_in else: @@ -35,36 +35,36 @@ def pyhexwatershed_read_model_configuration_file(sFilename_configuration_in,\ sMesh_type = aConfig["sMesh_type"] pass - if iCase_index_in is not None: + if iCase_index_in is not None: iCase_index = iCase_index_in - else: + else: iCase_index = int( aConfig['iCase_index']) - pass + pass - if iFlag_stream_burning_topology_in is not None: + if iFlag_stream_burning_topology_in is not None: iFlag_stream_burning_topology = iFlag_stream_burning_topology_in - else: + else: iFlag_stream_burning_topology = int( aConfig['iFlag_stream_burning_topology']) - pass - - if iFlag_elevation_profile_in is not None: + pass + + if iFlag_elevation_profile_in is not None: iFlag_elevation_profile = iFlag_elevation_profile_in - else: + else: iFlag_elevation_profile = int( aConfig['iFlag_elevation_profile']) - pass - - if iFlag_use_mesh_dem_in is not None: + pass + + if iFlag_use_mesh_dem_in is not None: iFlag_use_mesh_dem = iFlag_use_mesh_dem_in - else: + else: iFlag_use_mesh_dem = int( aConfig['iFlag_use_mesh_dem']) - pass - + pass + - if dResolution_meter_in is not None: + if dResolution_meter_in is not None: dResolution_meter = dResolution_meter_in - else: + else: dResolution_meter = float( aConfig['dResolution_meter']) - pass + pass aConfig["sDate"] = sDate aConfig["sMesh_type"] = sMesh_type @@ -72,16 +72,16 @@ def pyhexwatershed_read_model_configuration_file(sFilename_configuration_in,\ aConfig["iFlag_stream_burning_topology"] = iFlag_stream_burning_topology aConfig["iFlag_elevation_profile"] = iFlag_elevation_profile aConfig["iFlag_use_mesh_dem"] = iFlag_use_mesh_dem - + aConfig["dResolution_meter"] = dResolution_meter aConfig["sFilename_model_configuration"] = sFilename_configuration_in - - + + oPyhexwatershed = hexwatershedcase(aConfig) - oPyflowline = flowlinecase(aConfig , iFlag_standalone_in = 0,\ - sModel_in = 'pyflowline',\ - sWorkspace_output_in = oPyhexwatershed.sWorkspace_output_pyflowline) - + oPyflowline = flowlinecase(aConfig , iFlag_standalone_in = 0, + sModel_in = 'pyflowline', + sWorkspace_output_in = oPyhexwatershed.sWorkspace_output_pyflowline) + oPyhexwatershed.pPyFlowline = oPyflowline - - return oPyhexwatershed \ No newline at end of file + + return oPyhexwatershed diff --git a/setup.cfg b/setup.cfg index ca44670..298b5b6 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,5 +1,5 @@ [bumpversion] -current_version = 0.2.23 +current_version = 0.2.24 commit = True tag = True diff --git a/setup.py b/setup.py index 34204d3..93e876d 100644 --- a/setup.py +++ b/setup.py @@ -11,14 +11,19 @@ AUTHOR = "Chang Liao" AUTHOR_EMAIL = "chang.liao@pnnl.gov" URL = "https://github.com/changliao1025/pyhexwatershed" -VERSION = "0.2.23" +VERSION = "0.2.24" REQUIRES_PYTHON = ">=3.8.0" -KEYWORDS = "hexwatershed hexagon" +KEYWORDS = ["hexwatershed", + "hydrology", + "hydrologic modeling", + "hydrologic model", + "flow direction", + "hexagon"] REQUIRED = [ "numpy", - "matplotlib", - "gdal", + "gdal", + "shapely", "pyflowline" ] @@ -55,7 +60,6 @@ def get_data_files(sFolder_in): ( "external/hexwatershed/src/domain/" , get_data_files('external/hexwatershed/src/domain') ), ( "external/hexwatershed/src/json/" , get_data_files('external/hexwatershed/src/json') ) ] -print(data_files) HERE = os.path.abspath(os.path.dirname(__file__)) HERE = os.path.expandvars(HERE) @@ -190,7 +194,7 @@ def run(self): python_requires=REQUIRES_PYTHON, keywords=KEYWORDS, url=URL, - data_files=data_files, + #data_files=data_files, setup_requires=['setuptools'], packages=['pyhexwatershed'], package_data={ @@ -198,5 +202,8 @@ def run(self): }, install_requires=REQUIRED, cmdclass={"build_external": build_external}, - classifiers=CLASSIFY + classifiers=CLASSIFY, + extras_require={ + 'visualization': ['matplotlib', 'cartopy>=0.21.0'] + } ) From 4d6db966be99ae8bdd84be30a23658844ed6165c Mon Sep 17 00:00:00 2001 From: changliao1025 Date: Wed, 17 May 2023 10:06:19 -0700 Subject: [PATCH 3/3] update setup --- meta.yaml | 21 ++++++++++++++------- setup.py | 2 +- 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/meta.yaml b/meta.yaml index aa4ac38..06db6dc 100644 --- a/meta.yaml +++ b/meta.yaml @@ -12,8 +12,7 @@ build: host: platform: linux-64 script: - - python setup.py build_external - # Build the package for macOS (64-bit) + - python setup.py build_external host: platform: osx-64 script: @@ -33,19 +32,27 @@ requirements: - make - python - setuptool + - pip run: - python - numpy - - matplotlib + - matplotlib-base - gdal - pyflowline + +test: + imports: + - pyhexwatershed + commands: + - pip check + requires: + - pip about: home: https://github.com/changliao1025/pyhexwatershed - license: MIT - license_familY: MIT - license_file: LICENSE - summary: "HexWatershed" + summary: A mesh-independent flow direction model for hydrologic models + license: BSD-2-Clause + license_file: LICENSE.md extra: recipe-maintainers: diff --git a/setup.py b/setup.py index 93e876d..de3b04b 100644 --- a/setup.py +++ b/setup.py @@ -204,6 +204,6 @@ def run(self): cmdclass={"build_external": build_external}, classifiers=CLASSIFY, extras_require={ - 'visualization': ['matplotlib', 'cartopy>=0.21.0'] + 'visualization': ['cython', 'matplotlib', 'cartopy>=0.21.0'] } )