From c69ca55df103e20d481dd0c72e04e66bdd4af05b Mon Sep 17 00:00:00 2001 From: Adam Erispaha Date: Wed, 6 Jan 2021 16:38:46 -0500 Subject: [PATCH 1/3] update pyproj version and transform logic --- requirements.txt | 3 ++- setup.py | 2 +- swmmio/core.py | 12 +++++++----- swmmio/graphics/swmm_graphics.py | 17 +++++++---------- swmmio/tests/test_graphics.py | 10 +++++----- swmmio/utils/spatial.py | 32 +++++++++++++++++++++++--------- 6 files changed, 45 insertions(+), 31 deletions(-) diff --git a/requirements.txt b/requirements.txt index 6b8d20b..c09ccbf 100644 --- a/requirements.txt +++ b/requirements.txt @@ -5,9 +5,10 @@ pillow>=6.2.0 numpy>=1.16.4 pandas>=0.24.2 pyshp==2.1.0 -geojson==2.4.1 +geojson==2.5.0 networkx>=2.4 pyyaml>=3.12 recommonmark m2r # Run dependencies +pyproj>=3.0.0 diff --git a/setup.py b/setup.py index 6eb2658..8e9f6b6 100644 --- a/setup.py +++ b/setup.py @@ -36,7 +36,7 @@ def get_description(): 'numpy>=1.16.4', 'pandas>=0.24.2', 'pyshp==2.1.0', - 'geojson==2.4.1', + 'geojson>=2.4.1', 'networkx>=2.4', 'pyyaml>=3.12', ] diff --git a/swmmio/core.py b/swmmio/core.py index 537795f..861dd7a 100644 --- a/swmmio/core.py +++ b/swmmio/core.py @@ -2,10 +2,12 @@ # coding:utf-8 from time import ctime -import re import os -import pandas as pd import glob + +import pandas as pd +import numpy as np + from swmmio.utils import spatial from swmmio.utils import functions from swmmio.utils.dataframes import dataframe_from_rpt, get_link_coords, \ @@ -352,8 +354,8 @@ def to_crs(self, *args, **kwargs): :return: True >>> import swmmio - >>> m = swmmio.Model(MODEL_FULL_FEATURES_XY, crs="+init=EPSG:2272") - >>> m.to_crs("+init=EPSG:4326") # convert to WGS84 web mercator + >>> m = swmmio.Model(MODEL_FULL_FEATURES_XY, crs="EPSG:2272") + >>> m.to_crs("EPSG:4326") # convert to WGS84 web mercator >>> m.inp.coordinates X Y Name @@ -904,7 +906,7 @@ def inflows(self): if self._inflows_df is not None: return self._inflows_df inf = dataframe_from_inp(self.path, 'INFLOWS', quote_replace='_!!!!_') - self._inflows_df = inf.replace('_!!!!_', pd.np.nan) + self._inflows_df = inf.replace('_!!!!_', np.nan) return self._inflows_df @inflows.setter diff --git a/swmmio/graphics/swmm_graphics.py b/swmmio/graphics/swmm_graphics.py index 5c056ff..4ef80ca 100644 --- a/swmmio/graphics/swmm_graphics.py +++ b/swmmio/graphics/swmm_graphics.py @@ -1,19 +1,16 @@ # graphical functions for SWMM files -import pandas as pd +import os + +from PIL import Image, ImageDraw -from swmmio.defs.config import REPORT_DIR_NAME, BETTER_BASEMAP_PATH +from swmmio.defs.config import BETTER_BASEMAP_PATH from swmmio.graphics import config from swmmio.defs.constants import white from swmmio.graphics.utils import px_to_irl_coords, save_image -from swmmio.graphics.drawing import (annotate_streets, annotate_title, annotate_details, annotate_timestamp, - draw_conduit, draw_node) from swmmio.utils import spatial - -import os -from PIL import Image, ImageDraw - from swmmio.utils.spatial import centroid_and_bbox_from_coords -from swmmio.version_control.inp import INPSectionDiff +from swmmio.graphics.drawing import (annotate_streets, annotate_title, annotate_details, annotate_timestamp, + draw_conduit, draw_node) def _draw_basemap(draw, img, bbox, px_width, shift_ratio): @@ -126,7 +123,7 @@ def create_map(model=None, filename=None): filename = f'{model.name}.html' if model.crs: - model.to_crs("+init=EPSG:4326") + model.to_crs("EPSG:4326") else: raise ValueError('Model object must have a valid crs') diff --git a/swmmio/tests/test_graphics.py b/swmmio/tests/test_graphics.py index bc3d383..8210240 100644 --- a/swmmio/tests/test_graphics.py +++ b/swmmio/tests/test_graphics.py @@ -35,7 +35,7 @@ def test_draw_red_and_grey_nodes(): def test_web_map_01(): - m = swmmio.Model(MODEL_A_PATH, crs="+init=EPSG:2817") + m = swmmio.Model(MODEL_A_PATH, crs="EPSG:2817") with tempfile.TemporaryDirectory() as tempdir: fname = os.path.join(tempdir, 'test-map.html') sg.create_map(m, filename=fname) @@ -45,8 +45,8 @@ def test_web_map_01(): def test_centroid_and_bbox_from_coords(): - m = swmmio.Model(MODEL_A_PATH, crs="+init=EPSG:2817") - m.to_crs("+init=EPSG:4326") + m = swmmio.Model(MODEL_A_PATH, crs="EPSG:2817") + m.to_crs("EPSG:4326") c, bbox = centroid_and_bbox_from_coords(m.nodes.dataframe['coords']) assert c == pytest.approx((-70.97068, 43.74695), rel=1e-3) @@ -59,9 +59,9 @@ def test_centroid_and_bbox_from_coords(): def test_change_crs(): - m = swmmio.Model(MODEL_A_PATH, crs="+init=EPSG:2817") + m = swmmio.Model(MODEL_A_PATH, crs="EPSG:2817") v1 = m.inp.vertices - v2 = change_crs(m.inp.vertices, m.crs, "+init=EPSG:4326") + v2 = change_crs(m.inp.vertices, m.crs, "WGS84") assert v1.shape == v2.shape s = """ Name X Y diff --git a/swmmio/utils/spatial.py b/swmmio/utils/spatial.py index 6ba9478..f99a191 100644 --- a/swmmio/utils/spatial.py +++ b/swmmio/utils/spatial.py @@ -19,7 +19,7 @@ def change_crs(series, in_crs, to_crs): >>> proj4_str = '+proj=tmerc +lat_0=36.16666666666666 +lon_0=-94.5 +k=0.9999411764705882 +x_0=850000 +y_0=0 +datum=NAD83 +units=us-ft +no_defs' #"+init=EPSG:102698" >>> m.crs = proj4_str >>> nodes = m.nodes() - >>> change_crs(nodes['coords'], proj4_str, "+init=EPSG:4326") + >>> change_crs(nodes['coords'], proj4_str, "EPSG:4326") Name J3 [(39.236286854940964, -94.64346373821752)] 1 [(39.23851590020802, -94.64756446847099)] @@ -34,31 +34,45 @@ def change_crs(series, in_crs, to_crs): """ try: import pyproj + from pyproj import Transformer except ImportError: raise ImportError('pyproj module needed. get this package here: ', 'https://pypi.python.org/pypi/pyproj') # SET UP THE TO AND FROM COORDINATE PROJECTION - in_proj = pyproj.Proj(in_crs, preserve_units=True) - to_proj = pyproj.Proj(to_crs) + transformer = Transformer.from_crs(in_crs, to_crs, always_xy=True) # convert coords in coordinates, vertices, and polygons inp sections # transform to the typical 'WGS84' coord system def get_xys(xy_row): # need to reverse to lat/long after conversion - return [pyproj.transform(in_proj, to_proj, x, y) for x, y in xy_row] + return [transformer.transform(x, y) for x, y in xy_row] if isinstance(series, pd.Series): - return series.apply(lambda row: get_xys(row)) + + # unpack the nested coords + xs = [xy[0][0] for xy in series.to_list()] + ys = [xy[0][1] for xy in series.to_list()] + + # transform the whole series at once + xs_trans, ys_trans = transformer.transform(xs, ys) + + # increase nest level and return pd.Series + return pd.Series(index=series.index, data=[[coords] for coords in zip(xs_trans, ys_trans)]) + if isinstance(series, pd.DataFrame): - zipped_coords = list(zip(series.X, series.Y)) - df = pd.DataFrame(data=get_xys(zipped_coords), columns=["X", "Y"], index=series.index) + # zipped_coords = list(zip(series.X, series.Y)) + xs_trans, ys_trans = transformer.transform(series.X, series.Y) + df = pd.DataFrame(data=zip(xs_trans, ys_trans), columns=["X", "Y"], index=series.index) return df elif isinstance(series, (list, tuple)): if isinstance(series[0], (list, tuple)): - return get_xys(series) + # unpack the nested coords + xs = [x for x, y in series] + ys = [y for x, y in series] + return list(zip(transformer.transform(xs, ys))) else: - return get_xys([series]) + return transformer.transform(*series) def coords_series_to_geometry(coords, geomtype='linestring', dtype='geojson'): From 25374267413bdd280e391fd3fef3e04973398f54 Mon Sep 17 00:00:00 2001 From: Adam Erispaha Date: Wed, 6 Jan 2021 16:53:49 -0500 Subject: [PATCH 2/3] Set release version --- CHANGELOG.md | 19 +++++++++++++++++++ README.md | 2 +- swmmio/__init__.py | 2 +- 3 files changed, 21 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a1df5d8..0aeec34 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,22 @@ +## Version 0.4.7 (2021/01/06) + +### Issues Closed + +#### Bugs fixed + +* [Issue 118](https://github.com/aerispaha/swmmio/issues/118) - pyproj.transform is depreciated +* [Issue 111](https://github.com/aerispaha/swmmio/issues/111) - Setter property mismatch + +In this release 2 issues were closed. + +### Pull Requests Merged + +* [PR 113](https://github.com/aerispaha/swmmio/pull/113) - Read/write timeseries section of inp, by [@jackieff](https://github.com/jackieff) +* [PR 112](https://github.com/aerispaha/swmmio/pull/112) - Fixing setter references, by [@jackieff](https://github.com/jackieff) + +In this release 2 pull requests were closed. + + ## Version 0.4.6 (2020/10/05) ### Issues Closed diff --git a/README.md b/README.md index ce84d12..2a66f81 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ # swmmio -*v0.4.6 (2020/10/05)* +*v0.4.7 (2021/01/06)* [![Build status](https://ci.appveyor.com/api/projects/status/qywujm5w2wm0y2tv/branch/master?svg=true)](https://ci.appveyor.com/project/aerispaha/swmmio/branch/master) [![Build Status](https://travis-ci.com/aerispaha/swmmio.svg?branch=master)](https://travis-ci.com/aerispaha/swmmio) diff --git a/swmmio/__init__.py b/swmmio/__init__.py index c461589..1beb10e 100644 --- a/swmmio/__init__.py +++ b/swmmio/__init__.py @@ -6,7 +6,7 @@ '''Python SWMM Input/Output Tools''' -VERSION_INFO = (0, 4, 7, 'dev0') +VERSION_INFO = (0, 4, 7) __version__ = '.'.join(map(str, VERSION_INFO)) __author__ = 'Adam Erispaha' __copyright__ = 'Copyright (c) 2016' From f63f32d3efe1d538baf2f74ed18fed1fd90c1f81 Mon Sep 17 00:00:00 2001 From: Adam Erispaha Date: Wed, 6 Jan 2021 16:58:15 -0500 Subject: [PATCH 3/3] Restore dev version --- README.md | 9 --------- swmmio/__init__.py | 2 +- 2 files changed, 1 insertion(+), 10 deletions(-) diff --git a/README.md b/README.md index 2a66f81..33d5fad 100644 --- a/README.md +++ b/README.md @@ -11,15 +11,6 @@ ### Prerequisites `swmmio` functions primarily by interfacing with .inp and .rpt (input and report) files produced by SWMM. Functions within the `run_models` module rely on a SWMM5 engine which can be downloaded [here](https://www.epa.gov/water-research/storm-water-management-model-swmm). - -### Dependencies -* [pillow==6.0.0](https://python-pillow.org/) -* [numpy==1.16.4](https://numpy.org/) -* [pandas==0.24.2](https://github.com/pydata/pandas) -* [pyshp==2.1.0](https://github.com/GeospatialPython/pyshp) -* [geojson==2.4.1](https://pypi.org/project/geojson/) - - ### Installation: Before installation, it's recommended to first activate a [virtualenv](https://github.com/pypa/virtualenv) to not crowd your system's package library. If you don't use any of the dependencies listed above, this step is less important. SWMMIO can be installed via pip in your command line: diff --git a/swmmio/__init__.py b/swmmio/__init__.py index 1beb10e..771a95e 100644 --- a/swmmio/__init__.py +++ b/swmmio/__init__.py @@ -6,7 +6,7 @@ '''Python SWMM Input/Output Tools''' -VERSION_INFO = (0, 4, 7) +VERSION_INFO = (0, 4, 8, 'dev0') __version__ = '.'.join(map(str, VERSION_INFO)) __author__ = 'Adam Erispaha' __copyright__ = 'Copyright (c) 2016'