Exemplo n.º 1
0
def test_adjust_elevation_profile_no_change():
    lines = wkt_to_geoseries(['LINESTRING Z (0 0 8, 1 0 7, 2 0 6)'])
    n = swn.SurfaceWaterNetwork.from_lines(lines)
    n.adjust_elevation_profile()
    assert len(n.messages) == 0
    assert (lines == n.segments.geometry).all()
    expected_profiles = wkt_to_geoseries(['LINESTRING (0 8, 1 7, 2 6)'])
    assert (n.profiles == expected_profiles).all()
Exemplo n.º 2
0
def test_init_line_connects_to_middle():
    lines = wkt_to_geoseries([
        'LINESTRING Z (40 130 15, 60 100 14, 60 80 12)',
        'LINESTRING Z (70 130 15, 60 100 14)',
    ])
    n = swn.SurfaceWaterNetwork.from_lines(lines)
    assert len(n.warnings) == 0
    assert len(n.errors) == 1
    assert n.errors[0] == 'segment 1 connects to the middle of segment 0'
    assert len(n) == 2
    assert n.has_z is True
    assert list(n.segments.index) == [0, 1]
    assert list(n.segments['to_segnum']) == [-1, -1]
    assert list(n.segments['cat_group']) == [0, 1]
    assert list(n.segments['num_to_outlet']) == [1, 1]
    np.testing.assert_allclose(n.segments['dist_to_outlet'],
                               [56.05551, 31.622776])
    assert list(n.segments['sequence']) == [1, 2]
    assert list(n.segments['stream_order']) == [1, 1]
    np.testing.assert_allclose(n.segments['upstream_length'],
                               [56.05551, 31.622776])
    assert list(n.headwater) == [0, 1]
    assert list(n.outlets) == [0, 1]
    assert dict(n.to_segnums) == {}
    assert dict(n.from_segnums) == {}
    assert repr(n) == dedent('''\
        <SurfaceWaterNetwork: with Z coordinates
          2 segments: [0, 1]
          2 headwater: [0, 1]
          2 outlets: [0, 1]
          no diversions />''')
    if matplotlib:
        _ = n.plot()
        plt.close()
Exemplo n.º 3
0
def test_init_mismatch_3D():
    # Match in 2D, but not in Z dimension
    lines = wkt_to_geoseries([
        'LINESTRING Z (70 130 15, 60 100 14)',
        'LINESTRING Z (60 100 14, 60  80 12)',
        'LINESTRING Z (40 130 15, 60 100 13)',
    ])
    n = swn.SurfaceWaterNetwork.from_lines(lines)
    assert len(n.warnings) == 1
    assert n.warnings[0] == \
        'end of segment 2 matches start of segment 1 in 2D, but not in '\
        'Z dimension'
    assert len(n.errors) == 0
    assert len(n) == 3
    assert n.has_z is True
    assert list(n.segments.index) == [0, 1, 2]
    assert repr(n) == dedent('''\
        <SurfaceWaterNetwork: with Z coordinates
          3 segments: [0, 1, 2]
          2 headwater: [0, 2]
          1 outlets: [1]
          no diversions />''')
    if matplotlib:
        _ = n.plot()
        plt.close()
def test_lines_on_boundaries():
    m = flopy.modflow.Modflow()
    _ = flopy.modflow.ModflowDis(m,
                                 nrow=3,
                                 ncol=3,
                                 delr=100,
                                 delc=100,
                                 xul=0,
                                 yul=300)
    _ = flopy.modflow.ModflowBas(m)
    lines = wkt_to_geoseries([
        "LINESTRING (  0 320, 100 200)",
        "LINESTRING (100 200, 100 150, 150 100)",
        "LINESTRING (100 280, 100 200)",
        "LINESTRING (250 250, 150 150, 150 100)",
        "LINESTRING (150 100, 200   0, 300   0)",
    ])
    n = swn.SurfaceWaterNetwork.from_lines(lines)
    nm = swn.SwnModflow.from_swn_flopy(n, m)

    if matplotlib:
        _ = nm.plot()
        plt.close()

    # Check dataframes
    # TODO: code needs to be improved for this type of case
    assert len(nm.reaches) == 7
    assert len(np.unique(nm.reaches.iseg)) == 5
    assert len(nm.segments) == 5
    assert nm.segments["in_model"].sum() == 5
def test_linemerge_reaches_2():
    n = swn.SurfaceWaterNetwork.from_lines(
        wkt_to_geoseries([
            "LINESTRING(103.48 235.46,103.48 179.46,95.48 171.46,95.48 163.46,"
            "103.48 155.46,103.48 139.46,119.48 123.46,199.48 123.46,"
            "207.48 115.46,215.48 115.46,223.48 107.46,239.48 107.46,247.48 99.46,"
            "255.48 99.46,271.48 83.46,271.48 75.46,279.48 67.46,279.48 59.46,"
            "287.48 51.46,287.48 43.46,295.48 35.46,295.48 3.46,303.48 -4.54)"
        ]))
    m = flopy.modflow.Modflow()
    _ = flopy.modflow.ModflowDis(m,
                                 nrow=2,
                                 ncol=3,
                                 delr=100.0,
                                 delc=100.0,
                                 xul=0,
                                 yul=200)
    _ = flopy.modflow.ModflowBas(m, ibound=np.array([[1, 1, 0], [1, 1, 1]]))
    nm = swn.SwnModflow.from_swn_flopy(n, m)

    assert len(nm.reaches) == 4
    assert list(nm.reaches.i) == [0, 0, 0, 1]
    assert list(nm.reaches.j) == [1, 0, 1, 2]
    np.testing.assert_array_almost_equal(nm.reaches.rchlen,
                                         [25.461, 20.784, 134.863, 178.51], 3)
    assert repr(nm) == dedent("""\
        <SwnModflow: flopy mf2005 'modflowtest'
          4 in reaches (reachID): [1, 2, 3, 4]
          1 stress period with perlen: [1.0] />""")
    if matplotlib:
        _ = nm.plot()
        plt.close()
Exemplo n.º 6
0
def test_init_geoseries():
    gs = wkt_to_geoseries(valid_lines_list, geom_name='foo')
    n = swn.SurfaceWaterNetwork.from_lines(gs)
    assert len(n.warnings) == 0
    assert len(n.errors) == 0
    assert len(n) == 3
    assert list(n.segments.index) == [0, 1, 2]
    assert n.has_z is True
    v = pd.Series([3.0, 2.0, 4.0])
    a = n.accumulate_values(v)
    assert dict(a) == {0: 9.0, 1: 2.0, 2: 4.0}
def test_reach_barely_outside_ibound():
    n = swn.SurfaceWaterNetwork.from_lines(
        wkt_to_geoseries([
            "LINESTRING (15 125, 70 90, 120 120, 130 90, "
            "150 110, 180 90, 190 110, 290 80)"
        ]))
    m = flopy.modflow.Modflow()
    flopy.modflow.ModflowDis(m,
                             nrow=2,
                             ncol=3,
                             delr=100.0,
                             delc=100.0,
                             xul=0.0,
                             yul=200.0)
    flopy.modflow.ModflowBas(m, ibound=np.array([[1, 1, 1], [0, 0, 0]]))
    nm = swn.SwnModflow.from_swn_flopy(n, m, reach_include_fraction=0.8)

    assert len(nm.reaches) == 3
    assert list(nm.reaches.segnum) == [0, 0, 0]
    assert list(nm.reaches.i) == [0, 0, 0]
    assert list(nm.reaches.j) == [0, 1, 2]
    assert list(nm.reaches.iseg) == [1, 1, 1]
    assert list(nm.reaches.ireach) == [1, 2, 3]
    np.testing.assert_array_almost_equal(nm.reaches.rchlen,
                                         [100.177734, 152.08736, 93.96276], 5)
    expected_reaches_geom = wkt_to_geoseries([
        "LINESTRING (15 125, 54.3 100, 70 90, 86.7 100, 100 108)",
        "LINESTRING (100 108, 120 120, 126.7 100, 130 90, 140 100, 150 110, "
        "165 100, 180 90, 185 100, 190 110, 200 107)",
        "LINESTRING (200 107, 223.3 100, 290 80)"
    ])
    expected_reaches_geom.index += 1
    assert nm.reaches.geom_equals_exact(expected_reaches_geom, 0.1).all()
    assert repr(nm) == dedent("""\
        <SwnModflow: flopy mf2005 'modflowtest'
          3 in reaches (reachID): [1, 2, 3]
          1 stress period with perlen: [1.0] />""")
    if matplotlib:
        _ = nm.plot()
        plt.close()
def test_linemerge_reaches():
    n = swn.SurfaceWaterNetwork.from_lines(
        wkt_to_geoseries([
            "LINESTRING (30 180, 80 170, 120 210, 140 210, 190 110, "
            "205 90, 240 60, 255 35)"
        ]))
    m = flopy.modflow.Modflow()
    _ = flopy.modflow.ModflowDis(m,
                                 nrow=3,
                                 ncol=3,
                                 delr=100.0,
                                 delc=100.0,
                                 xul=0.0,
                                 yul=300.0)
    _ = flopy.modflow.ModflowBas(m)
    nm = swn.SwnModflow.from_swn_flopy(n, m)

    assert len(nm.reaches) == 5
    assert list(nm.reaches.i) == [1, 1, 0, 1, 2]
    assert list(nm.reaches.j) == [0, 1, 1, 1, 2]
    np.testing.assert_array_almost_equal(
        nm.reaches.rchlen, [79.274, 14.142, 45.322, 115.206, 85.669], 3)
    expected_reaches_geom = wkt_to_geoseries([
        "LINESTRING (30 180, 80 170, 100 190)",
        "LINESTRING (100 190, 110 200)",
        "LINESTRING (110 200, 120 210, 140 210, 145 200)",
        "LINESTRING (145 200, 190 110, 197.5 100, 198.75 98.33333333333334)",
        "LINESTRING (198.75 98.33333333333334, 200 96.66666666666667, "
        "205 90, 240 60, 255 35)"
    ])
    expected_reaches_geom.index += 1
    assert nm.reaches.geom_equals_exact(expected_reaches_geom, 0).all()
    assert repr(nm) == dedent("""\
        <SwnModflow: flopy mf2005 'modflowtest'
          5 in reaches (reachID): [1, 2, ..., 4, 5]
          1 stress period with perlen: [1.0] />""")
    if matplotlib:
        _ = nm.plot()
        plt.close()
Exemplo n.º 9
0
def test_init_segments_loc():
    lines = wkt_to_geoseries([
        "LINESTRING (60 100, 60  80)",
        "LINESTRING (40 130, 60 100)",
        "LINESTRING (70 130, 60 100)",
        "LINESTRING (60  80, 70  70)",
    ])
    lines.index += 100
    n1 = swn.SurfaceWaterNetwork.from_lines(lines)
    assert list(n1.outlets) == [103]
    # Create by slicing another GeoDataFrame, but check to_segnums
    n2 = swn.SurfaceWaterNetwork(n1.segments.loc[100:102])
    assert len(n2.segments) == 3
    assert list(n2.outlets) == [100]
    assert dict(n2.to_segnums) == {101: 100, 102: 100}
def test_linemerge_reaches_3():
    lines = wkt_to_geoseries([
        "LINESTRING(-9 295,63 295,71 303,87 303,95 295,119 295,143 271,"
        "143 255,151 247,167 247,175 239,183 239,191 247,255 247,263 255,"
        "271 255,279 247,295 247,303 239,303 207,271 175,255 175,247 167,"
        "239 167,215 143,215 135,207 127,207 119,199 111,199 87,191 79,"
        "191 39,207 23,223 23,231 31,239 31,255 47,263 47,271 55,279 55,"
        "287 63,295 63,303 71,311 71,319 79,327 79,335 87,343 87,351 95,"
        "367 95,375 103,391 103,399 111,423 111,439 95)",
        "LINESTRING(431 415,391 375,391 303,383 295,383 287,375 279,375 263,"
        "383 255,391 255,399 247,431 247,439 255,447 255,455 263,463 263,"
        "471 271,495 271,527 239,527 231,535 223,535 215,527 207,527 199,"
        "503 175,495 175,487 167,479 167,447 135,447 119,439 111,439 95)",
        "LINESTRING(439 95,439 71,471 39,503 39,511 47,551 47,607 -9)",
    ])
    lines.index += 100
    n = swn.SurfaceWaterNetwork.from_lines(lines)
    m = flopy.modflow.Modflow()
    _ = flopy.modflow.ModflowDis(m,
                                 nrow=4,
                                 ncol=6,
                                 delr=100.0,
                                 delc=100.0,
                                 xul=0,
                                 yul=400)
    _ = flopy.modflow.ModflowBas(m)
    nm = swn.SwnModflow.from_swn_flopy(n, m)

    assert len(nm.reaches) == 22
    assert list(nm.reaches.segnum) == [100] * 13 + [101] * 7 + [102] * 2
    assert list(nm.reaches.i) == \
        [1, 0, 1, 1, 1, 1, 1, 2, 3, 3, 3, 2, 2, 0, 0, 1, 1, 1, 2, 2, 3, 3]
    assert list(nm.reaches.j) == \
        [0, 0, 0, 1, 2, 3, 2, 2, 1, 2, 3, 3, 4, 4, 3, 3, 4, 5, 5, 4, 4, 5]
    assert list(nm.reaches.iseg) == [1] * 13 + [2] * 7 + [3] * 2
    assert list(nm.reaches.ireach) == \
        [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 1, 2, 3, 4, 5, 6, 7, 1, 2]
    np.testing.assert_array_almost_equal(nm.reaches.rchlen, [
        79.1, 24.5, 12.1, 135.9, 108.7, 40.5, 5.7, 143.2, 88.0, 121.5, 85.3,
        32.6, 45.6, 43.8, 89.0, 74.0, 112.0, 83.8, 37.9, 112.9, 98.3, 133.5
    ], 1)
    assert repr(nm) == dedent("""\
        <SwnModflow: flopy mf2005 'modflowtest'
          22 in reaches (reachID): [1, 2, ..., 21, 22]
          1 stress period with perlen: [1.0] />""")
    if matplotlib:
        _ = nm.plot(cmap='nipy_spectral')
        plt.close()
Exemplo n.º 11
0
def test_adjust_elevation_profile_use_min_slope():
    lines = wkt_to_geoseries(['LINESTRING Z (0 0 8, 1 0 9)'])
    n = swn.SurfaceWaterNetwork.from_lines(lines)
    n.adjust_elevation_profile()
    n.profiles = round_coords(n.profiles)
    n.segments.geometry = round_coords(n.segments.geometry)
    assert len(n.messages) == 1
    assert n.messages[0] == \
        'segment 0: adjusted 1 coordinate elevation by 1.001'
    expected = wkt_to_geoseries(['LINESTRING Z (0 0 8, 1 0 7.999)'])
    assert (expected == n.segments.geometry).all()
    expected_profiles = wkt_to_geoseries(['LINESTRING (0 8, 1 7.999)'])
    assert (n.profiles == expected_profiles).all()

    lines = wkt_to_geoseries(['LINESTRING Z (0 0 8, 1 0 9, 2 0 6)'])
    n = swn.SurfaceWaterNetwork.from_lines(lines)
    n.adjust_elevation_profile(0.1)
    assert len(n.messages) == 1
    assert n.messages[0] == \
        'segment 0: adjusted 1 coordinate elevation by 1.100'
    expected = wkt_to_geoseries(['LINESTRING Z (0 0 8, 1 0 7.9, 2 0 6)'])
    assert (expected == n.segments.geometry).all()
    expected_profiles = wkt_to_geoseries(['LINESTRING (0 8, 1 7.9, 2 6)'])
    assert (n.profiles == expected_profiles).all()

    lines = wkt_to_geoseries(['LINESTRING Z (0 0 8, 1 0 5, 2 0 6, 3 0 5)'])
    n = swn.SurfaceWaterNetwork.from_lines(lines)
    n.adjust_elevation_profile(0.2)
    assert len(n.messages) == 1
    assert n.messages[0] == \
        'segment 0: adjusted 2 coordinate elevations between 0.400 and 1.200'
    expected = wkt_to_geoseries(
        ['LINESTRING Z (0 0 8, 1 0 5, 2 0 4.8, 3 0 4.6)'])
    assert (expected == n.segments.geometry).all()
    expected_profiles = wkt_to_geoseries(
        ['LINESTRING (0 8, 1 5, 2 4.8, 3 4.6)'])
    assert (n.profiles == expected_profiles).all()
def test_init_all_diverge():
    # Lines all diverge from the same place
    lines = wkt_to_geoseries([
        'LINESTRING Z (60 100 15, 40 130 14)',
        'LINESTRING Z (60 100 16, 70 130 14)',
        'LINESTRING Z (60 100 15, 60  80 12)',
    ])
    n = swn.SurfaceWaterNetwork(lines)
    assert len(n.warnings) == 4
    assert n.warnings[0] == \
        'starting segment 0 matches start of segment 1 in 2D, '\
        'but not in Z dimension'
    assert len(n.errors) == 1
    assert n.errors[0] == \
        'starting coordinate (60.0, 100.0) matches start segments: ' + \
        str(set([0, 1, 2]))
    assert len(n) == 3
    assert n.has_z is True
    assert list(n.segments.index) == [0, 1, 2]
    assert list(n.segments['to_segnum']) == [-1, -1, -1]
    assert list(n.segments['num_to_outlet']) == [1, 1, 1]
    assert list(n.segments['cat_group']) == [0, 1, 2]
    np.testing.assert_allclose(
        n.segments['dist_to_outlet'], [36.05551, 31.622776, 20.0])
    assert list(n.segments['sequence']) == [1, 2, 3]
    assert list(n.segments['stream_order']) == [1, 1, 1]
    np.testing.assert_allclose(
        n.segments['upstream_length'], [36.05551, 31.622776, 20.0])
    assert list(n.headwater) == [0, 1, 2]
    assert list(n.outlets) == [0, 1, 2]
    assert dict(n.to_segnums) == {}
    assert n.from_segnums == {}
    assert repr(n) == dedent('''\
        <SurfaceWaterNetwork: with Z coordinates
          3 segments: [0, 1, 2]
          3 headwater: [0, 1, 2]
          3 outlets: [0, 1, 2]
          no diversions />''')
    if matplotlib:
        _ = n.plot()
        plt.close()
def test_outlet_series():
    # make a network with outlet on index 2
    n = swn.SurfaceWaterNetwork(wkt_to_geoseries([
        'LINESTRING Z (40 130 15, 60 100 14)',
        'LINESTRING Z (70 130 15, 60 100 14)',
        'LINESTRING Z (60 100 14, 60  80 12)',
    ]))
    # from scalar
    v = n._outlet_series(8.0)
    assert list(v.index) == [2]
    assert list(v) == [8.0]
    assert v.name is None
    v = n._outlet_series('$VAL$')
    assert list(v) == ['$VAL$']
    # from list
    v = n._outlet_series([8])
    assert list(v.index) == [2]
    assert list(v) == [8]
    assert v.name is None
    v = n._outlet_series(['$VAL_out$'])
    assert list(v.index) == [2]
    assert list(v) == ['$VAL_out$']
    assert v.name is None
    # from Series
    s = pd.Series([5.0], index=[2])
    v = n._outlet_series(s)
    assert list(v.index) == [2]
    assert list(v) == [5.0]
    assert v.name is None
    s.name = 'foo'
    v = n._outlet_series(s)
    assert v.name == 'foo'
    # now break it
    s.index -= 1
    with pytest.raises(ValueError,
                       match='index is different than for outlets'):
        n._outlet_series(s)
Exemplo n.º 14
0
import swn
from swn.spatial import force_2d, round_coords, wkt_to_geoseries

from .conftest import matplotlib, plt

# a few static objects (not fixtures)

valid_lines_list = [
    'LINESTRING Z (60 100 14, 60  80 12)',
    'LINESTRING Z (40 130 15, 60 100 14)',
    'LINESTRING Z (70 130 15, 60 100 14)',
]

valid_df = swn.spatial.wkt_to_dataframe(valid_lines_list)

valid_lines = wkt_to_geoseries(valid_lines_list)

valid_polygons = wkt_to_geoseries([
    'POLYGON ((35 100, 75 100, 75  80, 35  80, 35 100))',
    'POLYGON ((35 135, 60 135, 60 100, 35 100, 35 135))',
    'POLYGON ((60 135, 75 135, 75 100, 60 100, 60 135))',
])


@pytest.fixture
def valid_n():
    return swn.SurfaceWaterNetwork.from_lines(valid_lines)


def test_init_errors():
    with pytest.raises(ValueError, match='segments must be a GeoDataFrame'):
from .conftest import datadir, matplotlib, plt
try:
    import flopy
except ImportError:
    pytest.skip("skipping tests that require flopy", allow_module_level=True)

mf6_exe = which("mf6")
requires_mf6 = pytest.mark.skipif(not mf6_exe, reason="requires mf6")
if mf6_exe is None:
    mf6_exe = "mf6"

# same valid network used in test_basic
n3d_lines = wkt_to_geoseries([
    "LINESTRING Z (60 100 14, 60  80 12)",
    "LINESTRING Z (40 130 15, 60 100 14)",
    "LINESTRING Z (70 130 15, 60 100 14)",
])


def get_basic_swn(has_z: bool = True, has_diversions: bool = False):
    if has_z:
        n = swn.SurfaceWaterNetwork.from_lines(n3d_lines)
    else:
        n = swn.SurfaceWaterNetwork.from_lines(force_2d(n3d_lines))
    if has_diversions:
        diversions = geopandas.GeoDataFrame(geometry=[
            Point(58, 97),
            Point(62, 97),
            Point(61, 89),
            Point(59, 89)
Exemplo n.º 16
0
def test_init_geom_type():
    wkt_list = valid_lines_list[:]
    wkt_list[1] = 'MULTILINESTRING Z ((70 130 15, 60 100 14))'
    lines = wkt_to_geoseries(wkt_list)
    with pytest.raises(ValueError, match='lines must all be LineString types'):
        swn.SurfaceWaterNetwork.from_lines(lines)
Exemplo n.º 17
0
import geopandas
import numpy as np
import pandas as pd
import pytest
from shapely.geometry import Point

import swn
import swn.file
from swn.spatial import wkt_to_geoseries

from .conftest import datadir

# same valid network used in test_basic
n3d_lines = wkt_to_geoseries([
    'LINESTRING Z (60 100 14, 60  80 12)',
    'LINESTRING Z (40 130 15, 60 100 14)',
    'LINESTRING Z (70 130 15, 60 100 14)',
])

valid_polygons = wkt_to_geoseries([
    'POLYGON ((35 100, 75 100, 75  80, 35  80, 35 100))',
    'POLYGON ((35 135, 60 135, 60 100, 35 100, 35 135))',
    'POLYGON ((60 135, 75 135, 75 100, 60 100, 60 135))',
])

diversions = geopandas.GeoDataFrame(geometry=[
    Point(58, 97), Point(62, 97),
    Point(61, 89), Point(59, 89)
])