Basic usage of SFRmaker in a scripting context

This example illustrates basic usage of SFRmaker in a scripting context. For examples of using SFRmaker with a configuration file, see the MERAS and Tyler Forks examples.

[1]:
import numpy as np
import matplotlib.pyplot as plt
import flopy
import sfrmaker

Input requirements

The most basic input requirements of SFRmaker are hydrography and a model grid. Optionally, a model and a DEM can be input, as demonstrated below. See the documentation for a more detailed description of inputs.

Hydrography

In this example, we will use data that has been downloaded from NHDPlus. The original file structure in the download has been maintained, allowing us to simply supply SFRmaker with a path to the NHDPlus files:

[2]:
NHDPlus_paths = '../tylerforks/NHDPlus/'

If we were dealing with more than one drainage basin, the NHDPlus file paths could be included in a list:

[3]:
NHDPlus_paths_list = ['/NHDPlusGL/NHDPlus04/',
                      '/NHDPlusMS/NHDPlus07/']

Creating a Lines instance from NHDPlus

The sfrmaker.Lines class includes functionality for reading and processing hydrography flowlines. This example shows how to create a Lines instance from NHDPlus data.

For large hydrography datasets, it is advantageous to filter the data when it is read in. The filter argument to sfrmaker.Lines accepts a shapefile path or tuple of bounding box coordinates. In either case, a bounding box tuple is created and passed to the filter method in the `fiona package <https://fiona.readthedocs.io/en/latest/manual.html>`__, which is fast.

[4]:
lns = sfrmaker.Lines.from_nhdplus_v2(NHDPlus_paths='../tylerforks/NHDPlus/',
                            bbox_filter='../tylerforks/grid.shp')

loading NHDPlus v2 hydrography data...
for basins:
../tylerforks/NHDPlus/

reading ../tylerforks/NHDPlus/NHDPlusAttributes/PlusFlow.dbf...
--> building dataframe... (may take a while for large shapefiles)

load finished in 0.07s

Getting routing information from NHDPlus Plusflow table...
finished in 0.03s

Alternatively, sfrmaker.Lines can be instantiated with separate arguments for each NHDPlus file used:

[5]:
lines = sfrmaker.Lines.from_nhdplus_v2(NHDFlowlines='../tylerforks/NHDPlus/NHDSnapshot/Hydrography/NHDFlowline.shp',
                                       PlusFlowlineVAA='../tylerforks/NHDPlus/NHDPlusAttributes/PlusFlowlineVAA.dbf',
                                       PlusFlow='../tylerforks/NHDPlus/NHDPlusAttributes/PlusFlow.dbf',
                                       elevslope='../tylerforks/NHDPlus/NHDPlusAttributes/elevslope.dbf',
                                       bbox_filter=(-90.625, 46.3788, -90.4634, 46.4586))

loading NHDPlus v2 hydrography data...

reading ../tylerforks/NHDPlus/NHDPlusAttributes/PlusFlow.dbf...
--> building dataframe... (may take a while for large shapefiles)

load finished in 0.02s

Getting routing information from NHDPlus Plusflow table...
finished in 0.03s

Creating a Lines instance from custom hydrography

Alternatively, a Lines instance can be created from any hydrography that includes the pertinent attribute fields, which must be specified:

[6]:
custom_lines = sfrmaker.Lines.from_shapefile(shapefile='../meras/flowlines.shp',
                                             id_column='COMID',  # arguments to sfrmaker.Lines.from_shapefile
                                             routing_column='tocomid',
                                             width1_column='width1',
                                             width2_column='width2',
                                             up_elevation_column='elevupsmo',
                                             dn_elevation_column='elevdnsmo',
                                             name_column='GNIS_NAME',
                                             attr_length_units='feet',  # units of source data
                                             attr_height_units='feet',  # units of source data
                                             )

Specifying a model grid from a flopy StructuredGrid instance

The next step is to specify a model grid. One option is to specify a flopy StructuredGrid instance. SFRmaker will then use this internally to create an instance of its own StructuredGrid class. In this case, the row and column spacing must be provided in the units of the projected coordinate reference system (CRS) that the model is in, which is typically meters. In this case, our model grid spacing is 250 feet, so we have to convert.

Specifying a CRS (via the crs argument) is also important, as it allows SFRmaker to automatically reproject any input data to the same CRS as the model grid. The best way to do this is with an EPSG code, as shown below.

See the flopy documentation for more details about StructuredGrid.

[7]:
delr = np.array([250 * 0.3048] * 160)  # cell spacing along a row
delc = np.array([250 * 0.3048] * 111)  # cell spacing along a column

flopy_grid = flopy.discretization.StructuredGrid(delr=delr, delc=delc,
                                                 xoff=682688, yoff=5139052,  # lower left corner of model grid
                                                 angrot=0,  # grid is unrotated
                                                 # projected coordinate system of model (UTM NAD27 zone 15 North)
                                                 crs=26715
                                                 )

Specifying a model grid from a shapefile

Another option is to create an SFRmaker StructuredGrid directly using a shapefile. While the basic underpinings are in place for SFRmaker to support unstructured grids, this option hasn’t been fully implemented yet.

Attribute fields with row and column information must be specified. An polygon defining the area where the SFR network will be created can optionally be specified here, or later in the creation of SFRData (see below).

[8]:
grid = sfrmaker.StructuredGrid.from_shapefile(shapefile='../tylerforks/grid.shp',
                                              icol='i',  # attribute field with row information
                                              jcol='j',  # attribute field with column information
                                              active_area='../tylerforks/active_area.shp'
                                              )

reading ../tylerforks/grid.shp...
--> building dataframe... (may take a while for large shapefiles)

reading ../tylerforks/active_area.shp...
--> building dataframe... (may take a while for large shapefiles)

With specification of active_area, the grid created above has an ``isfr`` array attribute designating which cells can have SFR:

[9]:
plt.imshow(grid.isfr, interpolation='nearest')
[9]:
<matplotlib.image.AxesImage at 0x7fcd514e5040>
../_images/notebooks_SFRmaker_demo_17_1.png

Using the modelgrid attached to a flopy model

If no grid is supplied as input, SFRmaker will try to use modelgrid attribute attached to a supplied flopy model instance. This only works if modelgrid is valid. Loading a flopy model with a valid model grid requires the grid information to be specified in the namefile header, and that the model be in the same units as the projected CRS. See the flopy documentation for more details

Specifying a model

While a model is not required to run SFRmaker, specifying a model is advantageous in that it allows SFRmaker to assign valid model layers for reaches. Models are specified as flopy model instances, which can be loaded or created from scratch (see the flopy documentation). In this case, we are loading a model:

[10]:
m = flopy.modflow.Modflow.load('tf.nam', model_ws='../tylerforks/tylerforks')
m
[10]:
MODFLOW 5 layer(s) 111 row(s) 160 column(s) 1 stress period(s)

Creating an SFRData instance

The sfrmaker.SFRData class is the primary object for creating or modifying an SFR dataset. A SFRData instance can be created from the Lines class using the to_sfr() method.

Either a flopy StructuredGrid or sfrmaker StructuredGrid can be supplied. While MODFLOW and flopy support specification of length units, these aren’t always specified in the model input files, so it is good practice to specifiy the units explicitly to SFRmaker.

[11]:
sfrdata = lines.to_sfr(grid=flopy_grid, model=m, model_length_units='feet')

SFRmaker version 0.11.3.post13.dev0+gb72646a

Creating sfr dataset...

Creating grid class instance from flopy Grid instance...
grid class created in 0.45s

Model grid information
structured grid
nnodes: 17,760
nlay: 1
nrow: 111
ncol: 160
model length units: undefined
crs: EPSG:26715
bounds: 682688.00, 5139052.00, 694880.00, 5147510.20
active area defined by: all cells

MODFLOW 5 layer(s) 111 row(s) 160 column(s) 1 stress period(s)

reprojecting hydrography from
EPSG:4269
to
EPSG:26715


Culling hydrography to active area...
starting lines: 45
remaining lines: 42
finished in 0.00s


Intersecting 42 flowlines with 17,760 grid cells...

Building spatial index...
finished in 0.85s

Intersecting 42 features...
42
finished in 0.14s

Setting up reach data... (may take a few minutes for large grids)
finished in 0.47s

Computing widths...

Dropping 48 reaches with length < 12.50 feet...

Repairing routing connections...
enforcing best segment numbering...

Setting up segment data...
Model grid information
structured grid
nnodes: 17,760
nlay: 1
nrow: 111
ncol: 160
model length units: undefined
crs: EPSG:26715
bounds: 682688.00, 5139052.00, 694880.00, 5147510.20
active area defined by: all cells


Time to create sfr dataset: 2.19s

The SFRData class

Internally, the SFRData class mostly uses the data model for the MODFLOW-2005 style SFR2 package (which includes MODFLOW-NWT), which organizes the input into segments and reaches. Segment and reach data are stored in the reach_data and segment_data attribute DataFrames. In addition to the MODFLOW-2005 data, reach numbers and their routing connections (as needed for MODFLOW-6) are also stored. On writing of SFR package input, MODFLOW-6 style input can be created via the sfrmaker.mf5to6 module.

[12]:
sfrdata.reach_data.loc[sfrdata.reach_data['rno'] == 1, 'strhc1'] = 5
[13]:
sfrdata.reach_data.head()
[13]:
rno node k i j iseg ireach rchlen width slope ... thts thti eps uhc outreach outseg asum line_id name geometry
511 1 17714 0 110 114 1 1 208.807938 1.000000 0.127779 ... 0.0 0.0 0.0 0.0 2 4 31.822330 1815013 None LINESTRING (691394.6396657812 5139052, 691410....
512 2 17715 0 110 115 1 2 294.098938 1.261243 0.060563 ... 0.0 0.0 0.0 0.0 3 4 108.465340 1815013 None LINESTRING (691451 5139079.028908214, 691471.0...
513 3 17716 0 110 116 1 3 41.622536 1.531957 0.333944 ... 0.0 0.0 0.0 0.0 4 4 159.629288 1815013 None LINESTRING (691527.2 5139123.064392628, 691538...
514 4 17556 0 109 116 1 4 220.366440 1.714090 0.092205 ... 0.0 0.0 0.0 0.0 5 4 199.556412 1815013 None LINESTRING (691538.8006061709 5139128.2, 69156...
515 5 17557 0 109 117 1 5 162.617325 1.950304 0.097331 ... 0.0 0.0 0.0 0.0 6 4 257.923126 1815013 None LINESTRING (691603.4 5139143.66283342, 691624....

5 rows × 23 columns

[14]:
sfrdata.segment_data.head()
[14]:
per nseg icalc outseg iupseg iprior nstrpts flow runoff etsw ... uhc1 hcond2 thickm2 elevdn width2 depth2 thts2 thti2 eps2 uhc2
0 0 1 1 4 0 0 0 0.0 0.0 0.0 ... 0.0 0.0 0.0 1297.867432 5.638623 0.0 0.0 0.0 0.0 0.0
1 0 2 1 4 0 0 0 0.0 0.0 0.0 ... 0.0 0.0 0.0 1297.867432 37.791649 0.0 0.0 0.0 0.0 0.0
2 0 3 1 6 0 0 0 0.0 0.0 0.0 ... 0.0 0.0 0.0 1278.149658 7.069631 0.0 0.0 0.0 0.0 0.0
3 0 4 1 6 0 0 0 0.0 0.0 0.0 ... 0.0 0.0 0.0 1278.149658 38.638088 0.0 0.0 0.0 0.0 0.0
4 0 5 1 10 0 0 0 0.0 0.0 0.0 ... 0.0 0.0 0.0 1211.286133 6.470501 0.0 0.0 0.0 0.0 0.0

5 rows × 35 columns

Sampling streambed top elevations from a DEM

While the above dataset contains streambed top elevations read from NHDPlus, a DEM can be sampled to obtain more accurate elevations. If the DEM elevation units are specified, SFRmaker will convert the elevations to model units if needed. See the Streambed_elevation_demo notebook for more information on how this works.

[15]:
sfrdata.set_streambed_top_elevations_from_dem('../tylerforks/dem_26715.tif',
                                              elevation_units='meters')
running rasterstats.zonal_stats on buffered LineStrings...
finished in 8.48s


Smoothing elevations...
finished in 0.10s

Assigning layers to the reaches

Once we have a valid set of streambed elevations, the reaches can be assigned to model layers.

[16]:
sfrdata.assign_layers()
[17]:
sfrdata.reach_data.head()
[17]:
rno node k i j iseg ireach rchlen width slope ... thts thti eps uhc outreach outseg asum line_id name geometry
511 1 17714 2 110 114 1 1 208.807938 1.000000 0.040094 ... 0.0 0.0 0.0 0.0 2 4 31.822330 1815013 None LINESTRING (691394.6396657812 5139052, 691410....
512 2 17715 2 110 115 1 2 294.098938 1.261243 0.003117 ... 0.0 0.0 0.0 0.0 3 4 108.465340 1815013 None LINESTRING (691451 5139079.028908214, 691471.0...
513 3 17716 2 110 116 1 3 41.622536 1.531957 0.207275 ... 0.0 0.0 0.0 0.0 4 4 159.629288 1815013 None LINESTRING (691527.2 5139123.064392628, 691538...
514 4 17556 2 109 116 1 4 220.366440 1.714090 0.028292 ... 0.0 0.0 0.0 0.0 5 4 199.556412 1815013 None LINESTRING (691538.8006061709 5139128.2, 69156...
515 5 17557 2 109 117 1 5 162.617325 1.950304 0.015271 ... 0.0 0.0 0.0 0.0 6 4 257.923126 1815013 None LINESTRING (691603.4 5139143.66283342, 691624....

5 rows × 23 columns

Running diagnostics

SFRData includes a run_diagnostics() method that executes the Flopy checker on the SFR package input. While the Flopy checks are only implemented for MODFLOW-2005 style SFR packages, run_diagnostics() works on MODFLOW-6 packages as well, by working of an attached MODFLOW-2005 representation of the MODFLOW-6 SFR input. The following checks are executed: * NaNs (not a number values, which will cause MODFLOW to crash) * consecutive segment and reach numbering * segment numbering that only increases in the downstream direction * circular routing sequences (reaches or segments routing back to themselves) * routing connection proximity: The length of routing connections, as determined by the distance between their cell centers, is compared to 1.25 times the diagonal distance across the cell containing the upstream reach. This benchmark length is equivalent to a diagonal connection between two square cells, where one cell had a spacing of 1.5 times the other cell (the maximum recommended increase in spacing between two adjacent cells; see Anderson and others, 2015). While this routing proximity check can be helpful for identifying egregious routing issues, in practice, it may not be uncommon for valid routing connections to violate this rule. For example, if the one_reach_per_cell option is used in constructing the SFR package with a large grid size, there may be numerous routing connections that extend across several cells. When non-adjacent routing connections are identified, the user can check the shapefile of routing connections to verify the results. * overlapping conductances: This check identifies instances of collocated reaches, where more than one reach has a connection to the groundwater flow solution in that cell. Collocated reaches may or may not present an issue for a particular model solution, but can potentially promote instability or spurious circulation of flow between the collocated reaches. * spurious streambed top elevations: Values < -10 or > 15,000 are flagged * downstream rises in streambed elevation * inconsistencies between streambed elevation and the model grid: This check looks for streambed bottoms below their respective cell bottoms, which will cause MODFLOW to halt execution, and streambed tops that are above the model top. The latter issue will not prevent MODFLOW from running, but may indicate problems with the input if the differences are large. For coarse grids in areas of high stream density (where there are often multiple streams in a cell), it may be impossible to ensure that all streambed top elevations are at or below the model top. Oftentimes, these reaches are dry anyways (for example, and ephemeral gully that runs off a bluff into a perennial stream, where the cell elevation is based on the elevation of the perennial stream). In any case, it is good practice to check the largest violations by comparing the SFRmaker shapefile output to a DEM and other data in a GIS environment. * suprious slopes: slopes of less than 0.0001 (which can lead to excessive stages with the SFR package’s Manning approximation) and greater than 1.0 are flagged.

[18]:
sfrdata.run_diagnostics(verbose=False)

Running Flopy v. 3.9.0.dev2 diagnostics...
wrote tf_SFR.chk

Writing an SFR package

Now we can write the package. By default, a MODFLOW-2005 style package is written to the current working directory or the model workspace of the attached model instance.

[19]:
sfrdata.write_package()
SFRmaker v. 0.11.3.post13.dev0+gb72646a

Running Flopy v. 3.9.0.dev2 diagnostics...
passed.

Checking for continuity in segment and reach numbering...
passed.

Checking for increasing segment numbers in downstream direction...
passed.

Checking for circular routing...
passed.

Checking reach connections for proximity...
5 segments with non-adjacent reaches found.
At segments:
41 20 21 22 23

5 segments with non-adjacent reaches found.
At segments:
41 20 21 22 23


Checking for model cells with multiple non-zero SFR conductances...
24 model cells with multiple non-zero SFR conductances found.
This may lead to circular routing between collocated reaches.
Nodes with overlapping conductances:
k       i       j       iseg    ireach  rchlen  strthick        strhc1
2       110     119     1       8       268.5836486816406       1.0     1.0
2       110     119     2       1       72.61438751220703       1.0     1.0
0       87      122     3       54      35.35249328613281       1.0     1.0
0       87      122     4       33      231.09567260742188      1.0     1.0
0       76      110     5       47      204.88766479492188      1.0     1.0
0       87      122     6       1       30.414600372314453      1.0     1.0
2       84      119     6       7       271.24835205078125      1.0     1.0
2       84      119     6       9       26.37481117248535       1.0     1.0
0       76      110     6       27      75.33216094970703       1.0     1.0
2       25      24      7       42      95.27275085449219       1.0     1.0
2       25      24      8       47      230.57635498046875      1.0     1.0
1       58      132     9       25      48.14010238647461       1.0     1.0
1       58      132     9       27      92.92947387695312       1.0     1.0
0       48      109     9       64      251.07447814941406      1.0     1.0
0       76      110     10      1       69.20076751708984       1.0     1.0
0       48      108     10      40      19.56378746032715       1.0     1.0
0       48      109     10      41      122.84815216064453      1.0     1.0
0       48      108     10      42      28.33331871032715       1.0     1.0
2       25      24      11      1       21.51937484741211       1.0     1.0
2       18      17      11      15      148.96444702148438      1.0     1.0
2       18      17      12      57      76.79739379882812       1.0     1.0
1       80      49      13      70      159.26600646972656      1.0     1.0
0       48      108     14      1       125.24523162841797      1.0     1.0
0       47      98      14      22      67.60189056396484       1.0     1.0
0       47      98      14      24      103.03018188476562      1.0     1.0
0       54      89      14      39      34.45417785644531       1.0     1.0
0       54      89      14      41      60.66257095336914       1.0     1.0
0       53      78      14      57      61.411861419677734      1.0     1.0
0       53      78      14      59      28.438196182250977      1.0     1.0
0       52      76      14      62      63.360740661621094      1.0     1.0
0       52      76      14      64      294.8589782714844       1.0     1.0
1       54      73      14      69      341.6566162109375       1.0     1.0
1       54      73      14      71      27.671581268310547      1.0     1.0
1       80      49      14      125     39.762516021728516      1.0     1.0
2       18      17      16      1       185.54652404785156      1.0     1.0
2       15      3       16      21      32.64251708984375       1.0     1.0
2       36      11      17      38      57.836700439453125      1.0     1.0
2       110     159     19      2       201.63583374023438      1.0     1.0
0       38      85      21      8       72.7103042602539        1.0     1.0
0       38      85      21      9       54.39541244506836       1.0     1.0
2       108     57      24      8       237.04415893554688      1.0     1.0
2       108     57      24      9       46.142940521240234      1.0     1.0
0       94      35      24      45      96.94855499267578       1.0     1.0
0       94      35      24      47      91.54985046386719       1.0     1.0
2       91      35      24      50      60.89990997314453       1.0     1.0
2       91      34      24      51      61.16813278198242       1.0     1.0
1       80      49      25      1       146.93106079101562      1.0     1.0
2       91      35      25      26      308.2864685058594       1.0     1.0
2       91      34      25      27      75.82389068603516       1.0     1.0
2       15      3       31      1       273.603271484375        1.0     1.0
2       36      11      36      1       263.1260681152344       1.0     1.0
2       110     159     38      1       24.2677001953125        1.0     1.0
2       91      34      42      1       130.52822875976562      1.0     1.0
1       92      30      42      6       66.65867614746094       1.0     1.0
1       92      30      42      8       252.91909790039062      1.0     1.0

Checking for streambed tops of less than -10...
passed.

Checking for streambed tops of greater than 15000...
passed.

Checking segment_data for downstream rises in streambed elevation...
Segment elevup and elevdn not specified for nstrm=-1439 and isfropt=1
passed.

Checking reach_data for downstream rises in streambed elevation...
passed.

Checking reach_data for inconsistencies between streambed elevations and the model grid...
1 reaches encountered with streambed above model top.
Model top violations:
i j iseg ireach strtop modeltop strhc1 reachID diff
49 15 18 19 922.1929321289062 920.3099975585938 1.0 786 -1.8829345703125


Checking segment_data for inconsistencies between segment end elevations and the model grid...
Segment elevup and elevdn not specified for nstrm=-1439 and isfropt=1
passed.

Checking for streambed slopes of less than 0.0001...
passed.

Checking for streambed slopes of greater than 1.0...
passed.

wrote tf_SFR.chk
wrote /home/runner/work/sfrmaker/sfrmaker/examples/Notebooks/../tylerforks/tylerforks/tf.sfr.

Writing a MODFLOW-6 SFR package

Alternatively, a MODFLOW-6 style SFR package can be written by specifying version='mf6'

[20]:
sfrdata.write_package(version='mf6')
SFRmaker v. 0.11.3.post13.dev0+gb72646a

Running Flopy v. 3.9.0.dev2 diagnostics...
passed.

Checking for continuity in segment and reach numbering...
passed.

Checking for increasing segment numbers in downstream direction...
passed.

Checking for circular routing...
passed.

Checking reach connections for proximity...
5 segments with non-adjacent reaches found.
At segments:
41 20 21 22 23

5 segments with non-adjacent reaches found.
At segments:
41 20 21 22 23


Checking for model cells with multiple non-zero SFR conductances...
24 model cells with multiple non-zero SFR conductances found.
This may lead to circular routing between collocated reaches.
Nodes with overlapping conductances:
k       i       j       iseg    ireach  rchlen  strthick        strhc1
2       110     119     1       8       268.5836486816406       1.0     1.0
2       110     119     2       1       72.61438751220703       1.0     1.0
0       87      122     3       54      35.35249328613281       1.0     1.0
0       87      122     4       33      231.09567260742188      1.0     1.0
0       76      110     5       47      204.88766479492188      1.0     1.0
0       87      122     6       1       30.414600372314453      1.0     1.0
2       84      119     6       7       271.24835205078125      1.0     1.0
2       84      119     6       9       26.37481117248535       1.0     1.0
0       76      110     6       27      75.33216094970703       1.0     1.0
2       25      24      7       42      95.27275085449219       1.0     1.0
2       25      24      8       47      230.57635498046875      1.0     1.0
1       58      132     9       25      48.14010238647461       1.0     1.0
1       58      132     9       27      92.92947387695312       1.0     1.0
0       48      109     9       64      251.07447814941406      1.0     1.0
0       76      110     10      1       69.20076751708984       1.0     1.0
0       48      108     10      40      19.56378746032715       1.0     1.0
0       48      109     10      41      122.84815216064453      1.0     1.0
0       48      108     10      42      28.33331871032715       1.0     1.0
2       25      24      11      1       21.51937484741211       1.0     1.0
2       18      17      11      15      148.96444702148438      1.0     1.0
2       18      17      12      57      76.79739379882812       1.0     1.0
1       80      49      13      70      159.26600646972656      1.0     1.0
0       48      108     14      1       125.24523162841797      1.0     1.0
0       47      98      14      22      67.60189056396484       1.0     1.0
0       47      98      14      24      103.03018188476562      1.0     1.0
0       54      89      14      39      34.45417785644531       1.0     1.0
0       54      89      14      41      60.66257095336914       1.0     1.0
0       53      78      14      57      61.411861419677734      1.0     1.0
0       53      78      14      59      28.438196182250977      1.0     1.0
0       52      76      14      62      63.360740661621094      1.0     1.0
0       52      76      14      64      294.8589782714844       1.0     1.0
1       54      73      14      69      341.6566162109375       1.0     1.0
1       54      73      14      71      27.671581268310547      1.0     1.0
1       80      49      14      125     39.762516021728516      1.0     1.0
2       18      17      16      1       185.54652404785156      1.0     1.0
2       15      3       16      21      32.64251708984375       1.0     1.0
2       36      11      17      38      57.836700439453125      1.0     1.0
2       110     159     19      2       201.63583374023438      1.0     1.0
0       38      85      21      8       72.7103042602539        1.0     1.0
0       38      85      21      9       54.39541244506836       1.0     1.0
2       108     57      24      8       237.04415893554688      1.0     1.0
2       108     57      24      9       46.142940521240234      1.0     1.0
0       94      35      24      45      96.94855499267578       1.0     1.0
0       94      35      24      47      91.54985046386719       1.0     1.0
2       91      35      24      50      60.89990997314453       1.0     1.0
2       91      34      24      51      61.16813278198242       1.0     1.0
1       80      49      25      1       146.93106079101562      1.0     1.0
2       91      35      25      26      308.2864685058594       1.0     1.0
2       91      34      25      27      75.82389068603516       1.0     1.0
2       15      3       31      1       273.603271484375        1.0     1.0
2       36      11      36      1       263.1260681152344       1.0     1.0
2       110     159     38      1       24.2677001953125        1.0     1.0
2       91      34      42      1       130.52822875976562      1.0     1.0
1       92      30      42      6       66.65867614746094       1.0     1.0
1       92      30      42      8       252.91909790039062      1.0     1.0

Checking for streambed tops of less than -10...
passed.

Checking for streambed tops of greater than 15000...
passed.

Checking segment_data for downstream rises in streambed elevation...
Segment elevup and elevdn not specified for nstrm=-1439 and isfropt=1
passed.

Checking reach_data for downstream rises in streambed elevation...
passed.

Checking reach_data for inconsistencies between streambed elevations and the model grid...
1 reaches encountered with streambed above model top.
Model top violations:
i j iseg ireach strtop modeltop strhc1 reachID diff
49 15 18 19 922.1929321289062 920.3099975585938 1.0 786 -1.8829345703125


Checking segment_data for inconsistencies between segment end elevations and the model grid...
Segment elevup and elevdn not specified for nstrm=-1439 and isfropt=1
passed.

Checking for streambed slopes of less than 0.0001...
passed.

Checking for streambed slopes of greater than 1.0...
passed.

wrote tf_SFR.chk
converting segment data to period data...
converting reach and segment data to package data...
wrote /home/runner/work/sfrmaker/sfrmaker/examples/Notebooks/../tylerforks/tylerforks/tf.sfr

Writing tables

The reach_data and segment_data tables can be written out to csv files for further processing:

[21]:
sfrdata.write_tables()
wrote tables/tf_sfr_reach_data.csv
wrote tables/tf_sfr_segment_data.csv

and then read back in to create an SFRData instance

[22]:
sfrdata2 = sfrmaker.SFRData.from_tables('tables/tf_sfr_reach_data.csv', 'tables/tf_sfr_segment_data.csv',
                                        grid=grid)
Model grid information
structured grid
nnodes: 17,760
nlay: 1
nrow: 111
ncol: 160
model length units: undefined
crs: EPSG:26715
bounds: 682688.00, 5139052.00, 694880.00, 5147510.20
active area defined by: isfr array

Writing shapefiles

Shapefiles can also be written to visualize the SFR package. These include: * hydrography linestrings associated with each reach * model cell polygons associated with each reach * outlet locations where water is leaving the model * routing connections (as lines drawn between cell centers) * the locations of specified inflows or any other period data * observation locations (if observations were supplied as input)

[23]:
sfrdata.write_shapefiles()
writing shps/tf_sfr_cells.shp... Done
writing shps/tf_sfr_outlets.shp... Done
writing shps/tf_sfr_lines.shp... Done
writing shps/tf_sfr_routing.shp... Done
No period data to export!
No observations to export!
No non-zero values of flow to export!