Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
50 changes: 50 additions & 0 deletions autotest/test_plot_cross_section.py
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,56 @@ def test_cross_section_invalid_line_representations_fail(line):
flopy.plot.PlotCrossSection(modelgrid=grid, line={"line": line})


@requires_pkg("shapely")
@pytest.mark.parametrize("view", ["bogus", "diagonal", "X", "Y"])
def test_cross_section_invalid_view_raises_error(view):
grid = structured_square_grid(side=10)
if view in ("X", "Y"):
# view is case-insensitive, these should not raise
flopy.plot.PlotCrossSection(
modelgrid=grid, line={"line": [(0, 0), (10, 10)]}, view=view
)
return
with pytest.raises(ValueError):
flopy.plot.PlotCrossSection(
modelgrid=grid, line={"line": [(0, 0), (10, 10)]}, view=view
)


@requires_pkg("shapely")
@pytest.mark.parametrize(
"line, expected_auto_direction",
[
# horizontal: x-span > y-span
([(0, 5.5), (10, 5.5)], "x"),
# vertical: y-span > x-span
([(5.5, 0), (5.5, 10)], "y"),
# diagonal, equal spans: falls to the "else" (y) branch since the
# comparison is a strict ">"
([(0, 0), (10, 10)], "y"),
],
)
def test_cross_section_view_forces_direction(line, expected_auto_direction):
grid = structured_square_grid(side=10)

auto_xc = flopy.plot.PlotCrossSection(modelgrid=grid, line={"line": line})
assert auto_xc.direction == expected_auto_direction

x_xc = flopy.plot.PlotCrossSection(modelgrid=grid, line={"line": line}, view="x")
assert x_xc.direction == "x"

y_xc = flopy.plot.PlotCrossSection(modelgrid=grid, line={"line": line}, view="y")
assert y_xc.direction == "y"


@pytest.mark.parametrize("onkey, expected_direction", [("row", "x"), ("column", "y")])
@pytest.mark.parametrize("view", ["auto", "x", "y"])
def test_cross_section_view_ignored_for_row_column(onkey, expected_direction, view):
grid = structured_square_grid(side=10)
xc = flopy.plot.PlotCrossSection(modelgrid=grid, line={onkey: 4}, view=view)
assert xc.direction == expected_direction


def test_plot_limits():
xymin, xymax = 0, 1000
cellsize = 50
Expand Down
24 changes: 14 additions & 10 deletions flopy/plot/crosssection.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,12 +52,16 @@ class PlotCrossSection:
cross-sectional width less than min_segment_length will be ignored
and not included in the plot. Default is 1e-02.
view : str
view can be used to force the view of the cross section when a line is provided.
"auto" is default and mimics the long term behavior of flopy, which decides
on the view by taking the maximum of the x and y direction of the cross
sectional line. "x" forces the view to be plotted from the x direction
(bottom of the unrotated grid). and "y" forces the view to be plotted from the
y-direction "left" or "right" side of the unrotated grid.
view can be used to force the view of the cross section when an
arbitrary line (line["line"]) is provided. "auto" is default and
mimics the long term behavior of flopy, which decides on the view
by taking the maximum of the x and y direction of the cross
sectional line. "x" forces the view to be plotted from the x
direction (bottom of the unrotated grid) and "y" forces the view to
be plotted from the y-direction ("left" or "right" side of the
unrotated grid). view has no effect when the cross section is
specified with line["row"] or line["column"], since the view is
already unambiguous in that case.
"""

def __init__(
Expand All @@ -72,6 +76,8 @@ def __init__(
view="auto",
):
view = view.lower()
if view not in ("auto", "x", "y"):
raise ValueError(f"view must be 'auto', 'x', or 'y', got {view!r}")
self.ax = ax
self.geographic_coords = geographic_coords
self.model = model
Expand Down Expand Up @@ -168,10 +174,8 @@ def __init__(
yp.append(v2)

xp, yp = self.mg.get_local_coords(xp, yp)
if (np.max(xp) - np.min(xp) > np.max(yp) - np.min(yp)) or view not in (
"auto",
"y",
):
xspan_gt_yspan = np.max(xp) - np.min(xp) > np.max(yp) - np.min(yp)
if view == "x" or (view == "auto" and xspan_gt_yspan):
# this is x-projection and we should buffer x by small amount
idx0 = np.argmax(xp)
idx1 = np.argmin(xp)
Expand Down
Loading