Skip to content

Commit

Permalink
Merge pull request #220 from pyswmm/fixdocs
Browse files Browse the repository at this point in the history
update sphinx version
  • Loading branch information
aerispaha authored Nov 27, 2024
2 parents 1a80e7b + b4a9269 commit cc7504a
Show file tree
Hide file tree
Showing 15 changed files with 228 additions and 45 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/documentation.yml
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ jobs:
path: './docs/build'

deploy:
if: startsWith(github.event.ref, 'refs/tags/v')
# if: startsWith(github.event.ref, 'refs/tags/v')
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
Expand Down
6 changes: 5 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,8 @@ _build/
*.thm

# env
venv/
venv/

# docs artifacts
docs/_build/
docs/site/
File renamed without changes
File renamed without changes
File renamed without changes
50 changes: 15 additions & 35 deletions docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,9 @@
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
#
from recommonmark.transform import AutoStructify
from m2r import MdInclude
# from recommonmark.transform import AutoStructify
# from m2r import MdInclude
from datetime import datetime
import os
import sys
import swmmio
Expand All @@ -23,11 +24,11 @@
# -- Project information -----------------------------------------------------

project = 'swmmio'
copyright = '2022, Adam Erispaha'
copyright = f'{datetime.now().year}, Adam Erispaha'
author = 'Adam Erispaha'

# The short X.Y version
version = ''
version = swmmio.__version__
# The full version, including alpha/beta/rc tags
release = swmmio.__version__

Expand All @@ -46,7 +47,8 @@
'sphinx.ext.coverage',
'sphinx.ext.mathjax',
'sphinx.ext.viewcode',
'recommonmark',
'sphinx.ext.autosummary',
'myst_parser',
]

# Add any paths that contain templates here, relative to this directory.
Expand All @@ -55,8 +57,10 @@
# The suffix(es) of source filenames.
# You can specify multiple suffix as a list of string:
#
source_suffix = ['.rst', '.md']
# source_suffix = '.rst'
source_suffix = {
'.rst': 'restructuredtext',
'.md': 'markdown',
}

# The master toctree document.
master_doc = 'index'
Expand All @@ -66,12 +70,12 @@
#
# This is also used if you do content translation via gettext catalogs.
# Usually you set "language" from the command line for these cases.
language = None
language = 'en'

# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
# This pattern also affects html_static_path and html_extra_path.
exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
exclude_patterns = []

# The name of the Pygments (syntax highlighting) style to use.
pygments_style = 'sphinx'
Expand All @@ -83,7 +87,7 @@
# a list of builtin themes.
#
# html_theme = 'alabaster'
html_theme = "sphinx_rtd_theme"
html_theme = "pydata_sphinx_theme"

# Theme options are theme-specific and customize the look and feel of a theme
# further. For a list of options available for each theme, see the
Expand All @@ -94,7 +98,7 @@
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ['.']
html_static_path = ['_static']

# Custom sidebar templates, must be a dictionary that maps document names
# to template names.
Expand Down Expand Up @@ -181,27 +185,3 @@
# A list of files that should not be packed into the epub file.
epub_exclude_files = ['search.html']


# -- Extension configuration -------------------------------------------------
def setup(app):
config = {
# 'url_resolver': lambda url: github_doc_root + url,
'auto_toc_tree_section': 'Contents',
'enable_eval_rst': True,
}
app.add_config_value('recommonmark_config', config, True)
app.add_transform(AutoStructify)

# from m2r to make `mdinclude` work
app.add_config_value('no_underscore_emphasis', False, 'env')
app.add_config_value('m2r_parse_relative_links', False, 'env')
app.add_config_value('m2r_anonymous_references', False, 'env')
app.add_config_value('m2r_disable_inline_math', False, 'env')
app.add_directive('mdinclude', MdInclude)


# custom logic
from shutil import copytree
import os
os.makedirs('_build/html/docs', exist_ok=True)
copytree('img', '_build/html/docs/img')
32 changes: 25 additions & 7 deletions docs/index.rst
Original file line number Diff line number Diff line change
@@ -1,20 +1,38 @@
.. mdinclude:: ../README.md
swmmio
========================

.. image:: _static/img/impact_of_option.png
:alt: Impact of Option


`swmmio` provides a Pythonic interface to the EPA Stormwater Management Model (SWMM)
allowing engineers to programmatically create, modify, and
analyze SWMM models.

With `swmmio`, model parameters encoded in the `.inp` file can be
retrieved conveniently as Pandas dataframes making it possible to make
automate your hydraulics and hydologic modeling workflow. After simulations are
completed, results in the `.rpt` file can also be retrieved as Pandas dataframes,
making post-processing automation trivial.



.. swmmio documentation master file, created by
sphinx-quickstart on Tue Nov 27 23:09:04 2018.
You can adapt this file completely to your liking, but it should at least
contain the root `toctree` directive.
Contents
==================

.. toctree::
:maxdepth: 2
:caption: Contents:

swmmio
elements
version_control
utils
graphics
reference/index
installing
usage


Indices and tables
==================
Expand Down
8 changes: 8 additions & 0 deletions docs/installing.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
### 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:

```console
pip install swmmio
```
2 changes: 1 addition & 1 deletion docs/swmmio.rst → docs/reference/core.rst
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
`swmmio` Core Objects
`swmmio` core objects
========================

.. automodule:: swmmio.core
Expand Down
File renamed without changes.
File renamed without changes.
20 changes: 20 additions & 0 deletions docs/reference/index.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
.. -*- coding: utf-8 -*-
Reference
*********
.. only:: html

:Release: |release|
:Date: |today|


.. toctree::
:maxdepth: 2

core
elements
utils
graphics
version_control

.. only:: html
File renamed without changes.
File renamed without changes.
153 changes: 153 additions & 0 deletions docs/usage.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
# Usage
The `swmmio.Model()` class provides the basic endpoint for interfacing with SWMM models. To get started, save a SWMM5
model (.inp) in a directory with its report file (.rpt). A few examples:

```python
import swmmio

# instantiate a swmmio model object
mymodel = swmmio.Model('/path/to/directory with swmm files')

# dataframe with useful data related to model nodes, conduits, and subcatchments
nodes = mymodel.nodes.dataframe
links = mymodel.links.dataframe
subs = mymodel.subcatchments.dataframe

# enjoy all the Pandas functions
nodes.head()

# write to a csv
nodes.to_csv('/path/mynodes.csv')

# calculate average and weighted average impervious
avg_imperviousness = subs.PercImperv.mean()
weighted_avg_imp = (subs.Area * subs.PercImperv).sum() / len(subs)
```

# Nodes and Links Objects
Specific sections of data from the inp and rpt can be extracted with `Nodes` and `Links` objects.
Although these are the same object-type of the `swmmio.Model.nodes` and `swmmio.Model.links`,
accessing them directly allows for custom control over what sections of data are retrieved.

```python
from swmmio import Model, Nodes
m = Model("coolest-model.inp")

# pass custom init arguments into the Nodes object instead of using default settings referenced by m.nodes()
nodes = Nodes(
model=m,
inp_sections=['junctions', 'storage', 'outfalls'],
rpt_sections=['Node Depth Summary', 'Node Inflow Summary'],
columns=[ 'InvertElev', 'MaxDepth', 'InitDepth', 'SurchargeDepth', 'MaxTotalInflow', 'coords']
)

# access data
nodes.dataframe
```

# Generating Graphics
Create an image (.png) visualization of the model. By default, pipe stress and node flood duration is
visualized if your model includes output data (a .rpt file should accompany the .inp).

```python
swmmio.draw_model(mymodel)
```

![Default Draw Output](_static/img/default_draw.png "Sewer Stress, Node Flooding")

Use pandas to calculate some interesting stats, and generate a image to highlight
what's interesting or important for your project:

```python
#isolate nodes that have flooded for more than 30 minutes
flooded_series = nodes.loc[nodes.HoursFlooded>0.5, 'TotalFloodVol']
flood_vol = sum(flooded_series) #total flood volume (million gallons)
flooded_count = len(flooded_series) #count of flooded nodes

#highlight these nodes in a graphic
nodes['draw_color'] = '#787882' #grey, default node color
nodes.loc[nodes.HoursFlooded>0.5, 'draw_color'] = '#751167' #purple, flooded nodes

#set the radius of flooded nodes as a function of HoursFlooded
nodes.loc[nodes.HoursFlooded>1, 'draw_size'] = nodes.loc[nodes.HoursFlooded>1, 'HoursFlooded'] * 12

#make the conduits grey, sized as function of their geometry
conds['draw_color'] = '#787882'
conds['draw_size'] = conds.Geom1

#add an informative annotation, and draw:
annotation = 'Flooded Volume: {}MG\nFlooded Nodes:{}'.format(round(flood_vol), flooded_count)
swmmio.draw_model(mymodel, annotation=annotation, file_path='flooded_anno_example.png')
```
![Flooded highlight](_static/img/flooded_anno_example.png "Node Flooding with annotation")

# Building Variations of Models
Starting with a base SWMM model, other models can be created by inserting altered data into a new inp file. Useful for sensitivity analysis or varying boundary conditions, models can be created using a fairly simple loop, leveraging the `modify_model` package.

For example, climate change impacts can be investigated by creating a set of models with varying outfall Fixed Stage elevations:

```python
import os
import swmmio

# initialize a baseline model object
baseline = swmmio.Model(r'path\to\baseline.inp')
rise = 0.0 #set the starting sea level rise condition

# create models up to 5ft of sea level rise.
while rise <= 5:

# create a dataframe of the model's outfalls
outfalls = baseline.inp.outfalls

# create the Pandas logic to access the StageOrTimeseries column of FIXED outfalls
slice_condition = outfalls.OutfallType == 'FIXED', 'StageOrTimeseries'

# add the current rise to the outfalls' stage elevation
outfalls.loc[slice_condition] = pd.to_numeric(outfalls.loc[slice_condition]) + rise
baseline.inp.outfalls = outfalls

# copy the base model into a new directory
newdir = os.path.join(baseline.inp.dir, str(rise))
os.mkdir(newdir)
newfilepath = os.path.join(newdir, baseline.inp.name + "_" + str(rise) + '_SLR.inp')

# Overwrite the OUTFALLS section of the new model with the adjusted data
baseline.inp.save(newfilepath)

# increase sea level rise for the next loop
rise += 0.25

```

# Access Model Network
The `swmmio.Model` class returns a Networkx MultiDiGraph representation of the model via that `network` parameter:
```python

# access the model as a Networkx MutliDiGraph
G = model.network

# iterate through links
for u, v, key, data in model.network.edges(data=True, keys=True):

print (key, data['Geom1'])
# do stuff with the network
```

# Running Models
Using the command line tool, individual SWMM5 models can be run by invoking the swmmio module in your shell as such:
```shell
python -m swmmio --run path/to/mymodel.inp
```
If you have many models to run and would like to take advantage of your machine's cores, you can start a pool of simulations with the `--start_pool` (or `-sp`) command. After pointing `-sp` to one or more directories, swmmio will search for SWMM .inp files and add all them to a multiprocessing pool. By default, `-sp` leaves 4 of your machine's cores unused. This can be changed via the `-cores_left` argument.
```shell
# run all models in models in directories Model_Dir1 Model_Dir2
python -m swmmio -sp Model_Dir1 Model_Dir2

# leave 1 core unused
python -m swmmio -sp Model_Dir1 Model_Dir2 -cores_left=1
```
<div class="warning">
<p class="first admonition-title">Warning</p>
<p class="last">Using all cores for simultaneous model runs can put your machine's CPU usage at 100% for extended periods of time. This probably puts stress on your hardware. Use at your own risk.</p>
</div>

0 comments on commit cc7504a

Please sign in to comment.