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

refactor(imports): add function to import optional packages #1262

Merged
merged 16 commits into from
Oct 13, 2021
Merged
Show file tree
Hide file tree
Changes from 14 commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
ddcf8db
refactor(imports): add function to import optional packages
jdhughes-usgs Oct 10, 2021
ed7997c
refactor(imports): add function to import optional packages
jdhughes-usgs Oct 11, 2021
e3dbd0e
refactor(imports): add function to import optional packages
jdhughes-usgs Oct 11, 2021
55d3995
refactor(imports): add function to import optional packages
jdhughes-usgs Oct 11, 2021
3110523
refactor(imports): add function to import optional packages
jdhughes-usgs Oct 11, 2021
9836755
refactor(imports): add function to import optional packages
jdhughes-usgs Oct 11, 2021
a167870
refactor(imports): add function to import optional packages
jdhughes-usgs Oct 11, 2021
5c8b069
refactor(imports): add function to import optional packages
jdhughes-usgs Oct 11, 2021
4dee6aa
refactor(imports): add function to import optional packages
jdhughes-usgs Oct 11, 2021
72ad51d
refactor(imports): add function to import optional packages
jdhughes-usgs Oct 11, 2021
99610dd
Merge remote-tracking branch 'upstream/develop' into std-imports
jdhughes-usgs Oct 11, 2021
abe2900
refactor(imports): add function to import optional packages
jdhughes-usgs Oct 11, 2021
76927da
refactor(imports): add function to import optional packages
jdhughes-usgs Oct 12, 2021
99e6dac
refactor(imports): add function to import optional packages
jdhughes-usgs Oct 12, 2021
5113cfd
refactor(imports): add function to import optional packages
jdhughes-usgs Oct 12, 2021
c6723f4
refactor(imports): add function to import optional packages
jdhughes-usgs Oct 13, 2021
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
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ For general modeling issues, please consult a modeling forum, such as the [MODFL
Installation
-----------------------------------------------

FloPy requires **Python** 3.7 (or higher) and **NumPy** 1.15 (or higher). Dependencies for optional FloPy methods are summarized [here](docs/flopy_method_dependencies.md).
FloPy requires **Python** 3.7 (or higher), **NumPy** 1.15.0 (or higher), and **matplotlib** 1.4.0 (or higher). Dependencies for optional FloPy methods are summarized [here](docs/flopy_method_dependencies.md).
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good move. Might as well just require matplotlib.


To install FloPy type:

Expand Down
8 changes: 2 additions & 6 deletions autotest/t005_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,7 @@ def test_modflow_unstructured():
lpf = flopy.mfusg.MfUsgLpf(mf)
assert isinstance(lpf, flopy.mfusg.MfUsgLpf)

wel = flopy.mfusg.MfUsgWel(
mf, stress_period_data={0: [[0, -100]]}
)
wel = flopy.mfusg.MfUsgWel(mf, stress_period_data={0: [[0, -100]]})
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Presumably this change and the other changes unrelated to this PR are simple black reformatting issues.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes this is a black reformatting change

assert isinstance(wel, flopy.mfusg.MfUsgWel)

ghb = flopy.modflow.ModflowGhb(
Expand All @@ -44,9 +42,7 @@ def test_modflow_unstructured():
# write well file
wel.write_file()
assert os.path.isfile(os.path.join(cpth, f"{mf.name}.wel")) is True
wel2 = flopy.mfusg.MfUsgWel.load(
os.path.join(cpth, f"{mf.name}.wel"), mf
)
wel2 = flopy.mfusg.MfUsgWel.load(os.path.join(cpth, f"{mf.name}.wel"), mf)
assert wel2.stress_period_data[0] == wel.stress_period_data[0]

# write ghb file
Expand Down
4 changes: 1 addition & 3 deletions autotest/t016_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,9 +106,7 @@ def test_usg_model():
dis = flopy.modflow.ModflowDis(mf, nlay=1, nrow=11, ncol=11)
bas = flopy.modflow.ModflowBas(mf)
lpf = flopy.mfusg.MfUsgLpf(mf)
wel = flopy.mfusg.MfUsgWel(
mf, stress_period_data={0: [[0, 5, 5, -1.0]]}
)
wel = flopy.mfusg.MfUsgWel(mf, stress_period_data={0: [[0, 5, 5, -1.0]]})
ghb = flopy.modflow.ModflowGhb(
mf,
stress_period_data={
Expand Down
2 changes: 1 addition & 1 deletion autotest/t069_test_vtkexportmodel.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
"""
Test vtk export_model function without packages_names definition
Test vtk export_model function without packages_names definition
"""

import os
Expand Down
16 changes: 10 additions & 6 deletions autotest/t075_test_ugrid.py
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,11 @@ def test_triangle_unstructured_grid():
xc, yc = tri.get_xcyc().T
ncpl = np.array([len(iverts)])
g = UnstructuredGrid(
vertices=verts, iverts=iverts, ncpl=ncpl, xcenters=xc, ycenters=yc,
vertices=verts,
iverts=iverts,
ncpl=ncpl,
xcenters=xc,
ycenters=yc,
)
assert len(g.grid_lines) == 8190
assert g.nnodes == g.ncpl == 2730
Expand Down Expand Up @@ -293,7 +297,7 @@ def test_voronoi_grid0(plot=False):
gridprops = vor.get_gridprops_vertexgrid()
ncpl = gridprops["ncpl"]
assert (
ncpl == answer_ncpl
ncpl == answer_ncpl
), f"Number of cells should be {answer_ncpl}. Found {ncpl}"

voronoi_grid = VertexGrid(**gridprops, nlay=1)
Expand Down Expand Up @@ -329,7 +333,7 @@ def test_voronoi_grid1(plot=False):
voronoi_grid = VertexGrid(**gridprops, nlay=1)
ncpl = gridprops["ncpl"]
assert (
ncpl == answer_ncpl
ncpl == answer_ncpl
), f"Number of cells should be {answer_ncpl}. Found {ncpl}"

if plot:
Expand Down Expand Up @@ -362,7 +366,7 @@ def test_voronoi_grid2(plot=False):
voronoi_grid = VertexGrid(**gridprops, nlay=1)
ncpl = gridprops["ncpl"]
assert (
ncpl == answer_ncpl
ncpl == answer_ncpl
), f"Number of cells should be {answer_ncpl}. Found {ncpl}"

if plot:
Expand Down Expand Up @@ -405,7 +409,7 @@ def test_voronoi_grid3(plot=False):
voronoi_grid = VertexGrid(**gridprops, nlay=1)
ncpl = gridprops["ncpl"]
assert (
ncpl == answer_ncpl
ncpl == answer_ncpl
), f"Number of cells should be {answer_ncpl}. Found {ncpl}"

if plot:
Expand Down Expand Up @@ -441,7 +445,7 @@ def test_voronoi_grid4(plot=False):
voronoi_grid = VertexGrid(**gridprops, nlay=1)
ncpl = gridprops["ncpl"]
assert (
ncpl == answer_ncpl
ncpl == answer_ncpl
), f"Number of cells should be {answer_ncpl}. Found {ncpl}"

if plot:
Expand Down
18 changes: 12 additions & 6 deletions autotest/t080_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
if not os.path.exists(gridgen_ws):
os.makedirs(gridgen_ws)


def test_mfusg():

name = "dummy"
Expand Down Expand Up @@ -113,18 +114,23 @@ def test_mfusg():

# test if single node idx works
one_hds = flopy.utils.HeadUFile(head_file).get_ts(idx=300)
if one_hds[0,1] != head[0][300]:
raise AssertionError("Error head from 'get_ts' != head from 'get_data'")
if one_hds[0, 1] != head[0][300]:
raise AssertionError(
"Error head from 'get_ts' != head from 'get_data'"
)

# test if list of nodes for idx works
nodes = [300,182,65]
nodes = [300, 182, 65]

multi_hds = flopy.utils.HeadUFile(head_file).get_ts(idx=nodes)
for i, node in enumerate(nodes):
if multi_hds[0, i+1] != head[0][node]:
raise AssertionError("Error head from 'get_ts' != head from 'get_data'")
if multi_hds[0, i + 1] != head[0][node]:
raise AssertionError(
"Error head from 'get_ts' != head from 'get_data'"
)

return

if __name__ == '__main__':

if __name__ == "__main__":
test_mfusg()
4 changes: 1 addition & 3 deletions autotest/t506_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -456,9 +456,7 @@ def test_mfusg():

# re-run with an LPF keyword specified. This would have thrown an error
# before the addition of ikcflag to mflpf.py (flopy 3.3.3 and earlier).
lpf = flopy.mfusg.MfUsgLpf(
m, novfc=True, nocvcorrection=True
)
lpf = flopy.mfusg.MfUsgLpf(m, novfc=True, nocvcorrection=True)
m.write_input()
m.run_model()

Expand Down
34 changes: 15 additions & 19 deletions docs/flopy_method_dependencies.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,31 +2,27 @@ Additional dependencies to use optional FloPy helper methods are listed below.

| Method | Python Package |
| ------------------------------------------------------------------------------------ | ------------------------------------------------------------------ |
| `.PlotMapView()` in `flopy.plot` | **matplotlib** >= 1.4 |
| `.PlotCrossSection()` in `flopy.plot` | **matplotlib** >= 1.4 |
| `.plot()` | **matplotlib** >= 1.4 |
| `.plot_shapefile()` | **matplotlib** >= 1.4 and **Pyshp** >= 1.2 |
| `.to_shapefile()` | **Pyshp** >= 1.2 |
| `.export(*.shp)` | **Pyshp** >= 1.2 |
| `.export(*.nc)` | **netcdf4** >= 1.1, and **python-dateutil** >= 2.4 |
| `.plot_shapefile()` | **Pyshp** >= 2.0.0 |
| `.to_shapefile()` | **Pyshp** >= 2.0.0 |
| `.export(*.shp)` | **Pyshp** >= 2.0.0 |
| `.export(*.nc)` | **netcdf4** >= 1.1, and **python-dateutil** >= 2.4.0 |
| `.export(*.tif)` | **rasterio** |
| `.export(*.asc)` in `flopy.utils.reference` `SpatialReference` class | **scipy.ndimage** |
| `.interpolate()` in `flopy.utils.reference` `SpatialReference` class | **scipy.interpolate** |
| `.interpolate()` in `flopy.mf6.utils.reference` `StructuredSpatialReference` class | **scipy.interpolate** |
| `._parse_units_from_proj4()` in `flopy.utils.reference` `SpatialReference` class | **pyproj** |
| `.get_dataframes()` in `flopy.utils.mflistfile` `ListBudget` class | **pandas** >= 0.15 |
| `.get_dataframes()` in `flopy.utils.observationfile` `ObsFiles` class | **pandas** >= 0.15 |
| `.get_dataframes()` in `flopy.utils.sfroutputfile` `ModflowSfr2` class | **pandas** >= 0.15 |
| `.get_dataframes()` in `flopy.utils.util_list` `MfList` class | **pandas** >= 0.15 |
| `.get_dataframes()` in `flopy.utils.zonebud` `ZoneBudget` class | **pandas** >= 0.15 |
| `.pivot_keyarray()` in `flopy.mf6.utils.arrayutils` `AdvancedPackageUtil` class | **pandas** >= 0.15 |
| `._get_vertices()` in `flopy.mf6.utils.binaryfile_utils` `MFOutputRequester` class | **pandas** >= 0.15 |
| `.get_dataframe()` in `flopy.mf6.utils.mfobservation` `Observations` class | **pandas** >= 0.15 |
| `.df()` in `flopy.modflow.mfsfr2` `SfrFile` class | **pandas** >= 0.15 |
| `.time_coverage()` in `flopy.export.metadata` `acc` class - ***used if available*** | **pandas** >= 0.15 |
| `.loadtxt()` in `flopy.utils.flopyio` - ***used if available*** | **pandas** >= 0.15 |
| `.get_dataframes()` in `flopy.utils.mflistfile` `ListBudget` class | **pandas** >= 0.15.0 |
| `.get_dataframes()` in `flopy.utils.observationfile` `ObsFiles` class | **pandas** >= 0.15.0 |
| `.get_dataframes()` in `flopy.utils.sfroutputfile` `ModflowSfr2` class | **pandas** >= 0.15.0 |
| `.get_dataframes()` in `flopy.utils.util_list` `MfList` class | **pandas** >= 0.15.0 |
| `.get_dataframes()` in `flopy.utils.zonebud` `ZoneBudget` class | **pandas** >= 0.15.0 |
| `.pivot_keyarray()` in `flopy.mf6.utils.arrayutils` `AdvancedPackageUtil` class | **pandas** >= 0.15.0 |
| `._get_vertices()` in `flopy.mf6.utils.binaryfile_utils` `MFOutputRequester` class | **pandas** >= 0.15.0 |
| `.get_dataframe()` in `flopy.mf6.utils.mfobservation` `Observations` class | **pandas** >= 0.15.0 |
| `.df()` in `flopy.modflow.mfsfr2` `SfrFile` class | **pandas** >= 0.15.0 |
| `.time_coverage()` in `flopy.export.metadata` `acc` class - ***used if available*** | **pandas** >= 0.15.0 |
| `.loadtxt()` in `flopy.utils.flopyio` - ***used if available*** | **pandas** >= 0.15.0 |
| `.generate_classes()` in `flopy.mf6.utils` | [**pymake**](https://github.com/modflowpy/pymake) |
| `.intersect()` in `flopy.discretization.VertexGrid` | **matplotlib** >= 1.4 |
| `GridIntersect()` in `flopy.utils.gridintersect` | **shapely** |
| `GridIntersect().plot_polygon()` in `flopy.utils.gridintersect` | **shapely** and **descartes** |
| `Raster()` in `flopy.utils.Raster` | **rasterio**, **affine**, and **scipy** |
Expand Down
22 changes: 16 additions & 6 deletions etc/environment.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,28 +2,38 @@ name: flopy
channels:
- conda-forge
dependencies:
# required
- python>=3.7
- numpy>=1.15.0
- matplotlib>=1.4.0

# testing
- pylint
- flake8
- black
- nose
- nose-timer
- coverage

# optional
- appdirs
- requests
- numpy>=1.15
- matplotlib
- bmipy
- python-dateutil>=2.4.0
- affine
- scipy
- pandas
- netcdf4
- pyshp
- pyshp>=2.0.0
- rasterio
- fiona
- descartes
- pyproj
- shapely
- geos
- geojson
- vtk
- vtk

# external dependencies
- requests

# MODFLOW API dependencies
- bmipy
4 changes: 0 additions & 4 deletions flopy/discretization/structuredgrid.py
Original file line number Diff line number Diff line change
Expand Up @@ -725,10 +725,6 @@ def map_polygons(self):
-------
list of Polygon objects
"""
try:
import matplotlib.path as mpath
except ImportError:
raise ImportError("matplotlib required to use this method")
cache_index = "xyzgrid"
if (
cache_index not in self._cache_dict
Expand Down
5 changes: 1 addition & 4 deletions flopy/discretization/unstructuredgrid.py
Original file line number Diff line number Diff line change
Expand Up @@ -471,10 +471,7 @@ def map_polygons(self):
-------
list or dict of matplotlib.collections.Polygon
"""
try:
from matplotlib.path import Path
except ImportError:
raise ImportError("matplotlib required to use this method")
from matplotlib.path import Path

cache_index = "xyzgrid"
if (
Expand Down
18 changes: 2 additions & 16 deletions flopy/discretization/vertexgrid.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,7 @@
import copy
import numpy as np

try:
from matplotlib.path import Path
except (ImportError, RuntimeError):
Path = None
from matplotlib.path import Path

from .grid import Grid, CachedData
from ..utils.geometry import is_clockwise
Expand Down Expand Up @@ -226,10 +223,6 @@ def map_polygons(self):
-------
list of Polygon objects
"""
try:
import matplotlib.path as mpath
except ImportError:
raise ImportError("matplotlib required to use this method")
cache_index = "xyzgrid"
if (
cache_index not in self._cache_dict
Expand All @@ -239,8 +232,7 @@ def map_polygons(self):
self._polygons = None
if self._polygons is None:
self._polygons = [
mpath.Path(self.get_cell_vertices(nn))
for nn in range(self.ncpl)
Path(self.get_cell_vertices(nn)) for nn in range(self.ncpl)
]

return copy.copy(self._polygons)
Expand Down Expand Up @@ -270,12 +262,6 @@ def intersect(self, x, y, local=False, forgive=False):
The CELL2D number

"""
if Path is None:
s = (
"Could not import matplotlib. Must install matplotlib "
"in order to use VertexGrid.intersect() method"
)
raise ImportError(s)

if local:
# transform x and y to real-world coordinates
Expand Down
19 changes: 7 additions & 12 deletions flopy/export/metadata.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
from flopy.utils.flopy_io import get_url_text
import numpy as np

try:
import pandas as pd
except:
pd = False
from ..utils.flopy_io import get_url_text
from ..utils import import_optional_dependency


class acdd:
Expand Down Expand Up @@ -194,13 +191,15 @@ def time_coverage(self):
-------

"""
pd = import_optional_dependency("pandas", errors="ignore")

l = self.sb["dates"]
tc = {}
for t in ["start", "end"]:
tc[t] = [d.get("dateString") for d in l if t in d["type"].lower()][
0
]
if not np.all(self.model_time.steady_state) and pd:
if not np.all(self.model_time.steady_state) and pd is not None:
# replace with times from model reference
tc["start"] = self.model_time.start_datetime
strt = pd.Timestamp(self.model_time.start_datetime)
Expand Down Expand Up @@ -260,7 +259,6 @@ def get_sciencebase_metadata(self, id):
url = urlbase.format(id)

import json
from flopy.utils.flopy_io import get_url_text

msg = "Need an internet connection to get metadata from ScienceBase."
text = get_url_text(url, error_msg=msg)
Expand All @@ -283,11 +281,8 @@ def get_sciencebase_xml_metadata(self):
metadata : dict
Dictionary of metadata
"""
try:
# use defusedxml to removed XML security vulnerabilities
import defusedxml.ElementTree as ET
except ImportError:
raise ImportError("DefusedXML must be installed to query metadata")
# use defusedxml to removed XML security vulnerabilities
ET = import_optional_dependency("defusedxml.ElementTree")

url = self.xmlfile
msg = "Need an internet connection to get metadata from ScienceBase."
Expand Down
Loading