Skip to content

Commit 28756e9

Browse files
authored
Merge pull request #33 from aerispaha/py3
Python 2/3 Compatibility
2 parents fbf93c4 + c6e11b5 commit 28756e9

31 files changed

+660
-88
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ private.py
44
private/
55
# Setuptools distribution folder.
66
/dist/
7+
/build/
78
# Python egg metadata, regenerated from source files by setuptools.
89
/*.egg-info
910
notes/

.travis.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
language: python
22
python:
33
- "2.7"
4-
# - "3.6"
4+
- "3.6"
55
# - "3.7"
66
# command to install dependencies
77
install:

README.md

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
# SWMMIO
2+
3+
[![Build status](https://ci.appveyor.com/api/projects/status/qywujm5w2wm0y2tv?svg=true)](https://ci.appveyor.com/project/aerispaha/swmmio)
4+
25
![Kool Picture](docs/img/impact_of_option.png?raw=true "Impact of Option")
36
SWMMIO is a set of python tools aiming to provide a means for version control and visualizing results from the EPA Stormwater Management Model (SWMM). Command line tools are also provided for running models individually and in parallel via Python's `multiprocessing` module. These tools are being developed specifically for the application of flood risk management, though most functionality is applicable to SWMM modeling in general.
47

@@ -8,7 +11,7 @@ SWMMIO functions primarily by interfacing with .inp and .rpt (input and report)
811

912

1013
### Dependencies
11-
* [pillow](http://python-pillow.org/): 3.0.0
14+
* [pillow](http://python-pillow.org/)
1215
* [matplotlib](http://matplotlib.org/)
1316
* [numpy](http://www.numpy.org/)
1417
* [pandas](https://github.com/pydata/pandas)
@@ -19,10 +22,6 @@ SWMMIO functions primarily by interfacing with .inp and .rpt (input and report)
1922
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:
2023

2124
```bash
22-
#on Windows:
23-
python -m pip install swmmio
24-
25-
#on Unix-type systems, i do this:
2625
pip install swmmio
2726
```
2827

appveyor.yml

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
#matrix:
2+
# fast_finish: true
3+
4+
#branches:
5+
# only:
6+
# - master
7+
# - /dev-.*/
8+
9+
environment:
10+
matrix:
11+
# For Python versions available on Appveyor, see
12+
# http://www.appveyor.com/docs/installed-software#python
13+
# The list here is complete (excluding Python 2.6, which
14+
# isn't covered by this document) at the time of writing.
15+
- PYTHON: "C:\\Python27"
16+
- PYTHON: "C:\\Python36"
17+
18+
install:
19+
- "%PYTHON%\\python setup.py develop"
20+
- "%PYTHON%\\python.exe -m pip install -r %APPVEYOR_BUILD_FOLDER%\\requirements.txt -q"
21+
22+
build: off
23+
24+
test_script:
25+
26+
- "%PYTHON%\\Scripts\\pytest %APPVEYOR_BUILD_FOLDER%"
27+
28+
# Asserting pep8 formatting checks (using autopep8 tool)
29+
# - ps: |
30+
# $output = C:\\Python36\\Scripts\\autopep8 -d --recursive .
31+
# if($output)
32+
# {
33+
# echo $output;
34+
# $host.SetShouldExit(1)
35+
# Write-Host "autopep8 failed:
36+
# Please this command locally:
37+
# 'autopep8 -i -a -r .'"
38+
# }

requirements.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# Build dependencies
22
#python
33
pytest
4-
pillow==3.0.0
4+
pillow
55
numpy
66
pandas
77
pyshp

setup.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,13 @@ def read(fname):
66
return open(os.path.join(os.path.dirname(__file__), fname)).read()
77

88

9-
VERSION = '0.2.1'
9+
VERSION = '0.3.0'
1010
AUTHOR_NAME = 'Adam Erispaha'
1111
AUTHOR_EMAIL = '[email protected]'
1212

1313
install_requires = [
14-
'pillow==3.0.0',
14+
# 'pillow==3.0.0',
15+
'Pillow',
1516
'numpy',
1617
'pandas',
1718
'pyshp',

swmmio/__main__.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
from .run_models.run import run_simple, run_hot_start_sequence
22
from .run_models import start_pool
3-
from swmmio import Model
3+
from .swmmio import Model
44
from itertools import chain
55
import os
66
import argparse
@@ -21,23 +21,23 @@
2121
if args.model_to_run is not None:
2222

2323
models_paths = [os.path.join(wd, f) for f in args.model_to_run]
24-
print 'Adding models to queue:\n\t{}'.format('\n\t'.join(models_paths))
24+
print('Adding models to queue:\n\t{}'.format('\n\t'.join(models_paths)))
2525

2626
#run the models in series (one after the other)
27-
map(run_simple, models_paths)
27+
list(map(run_simple, models_paths))
2828
# run_simple(args.model_to_run)
2929

3030
elif args.hotstart_model_to_run is not None:
3131
models_paths = [os.path.join(wd, f) for f in args.hotstart_model_to_run]
32-
print 'hotstart_model_to_run the model: {}'.format(args.hotstart_model_to_run)
32+
print('hotstart_model_to_run the model: {}'.format(args.hotstart_model_to_run))
3333
# m = Model(args.hotstart_model_to_run)
3434
# run_hot_start_sequence(m)#args.hotstart_model_to_run)
35-
map(run_hot_start_sequence, models_paths)
35+
list(map(run_hot_start_sequence, models_paths))
3636

3737
elif args.start_pool is not None:
3838

3939
models_dirs = [os.path.join(wd, f) for f in args.start_pool]
40-
print 'Searching for models in:\n\t{}'.format('\n\t'.join(models_dirs))
40+
print('Searching for models in:\n\t{}'.format('\n\t'.join(models_dirs)))
4141
#combine the segments and options (combinations) into one iterable
4242
inp_paths = []
4343
for root, dirs, files in chain.from_iterable(os.walk(path) for path in models_dirs):
@@ -50,8 +50,8 @@
5050
#call the main() function in start_pool.py
5151
start_pool.main(inp_paths, args.cores_left)
5252

53-
print "swmmio has completed running {} models".format(len(inp_paths))
53+
print("swmmio has completed running {} models".format(len(inp_paths)))
5454

5555

5656
else:
57-
print 'you need to pass in some args'
57+
print('you need to pass in some args')

swmmio/defs/sectionheaders.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
'[INFILTRATION]':'Subcatchment Suction HydCon IMDmax',
2626
'[Polygons]':'Name X Y',
2727
'[REPORT]':'Param Status',
28+
'[TAGS]':'ElementType Name Tag',
2829
#'[CURVES]':'Name Type X-Value Y-Value',
2930
#'[TIMESERIES]':'Name Date Time Value'
3031
}
@@ -41,6 +42,7 @@
4142
'Node Flooding Summary':'Name HoursFlooded MaxQ MaxDay MaxHr TotalFloodVol MaximumPondDepth',
4243
'Node Inflow Summary':'Name Type MaxLatInflow MaxTotalInflow MaxDay MaxHr LatInflowV TotalInflowV FlowBalErrorPerc XXX',
4344
'Node Surcharge Summary':'Name Type HourSurcharged MaxHeightAboveCrown MinDepthBelowRim',
45+
'Storage Volume Summary':'Name AvgVolume AvgPctFull EvapPctLoss ExfilPctLoss MaxVolume MaxPctFull MaxDay MaxFullHr MaxOutflow',
4446
'Node Depth Summary':'Name Type AvgDepth MaxNodeDepth MaxHGL MaxDay MaxHr',
4547
'Link Flow Summary':'Name Type MaxQ MaxDay MaxHr MaxV MaxQPerc MaxDPerc',
4648
'Subcatchment Results': 'Date Time PrecipInchPerHour LossesInchPerHr RunoffCFS',

swmmio/graphics/animate.py

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ def animateModel(model, startDtime=None, endDtime=None, **kwargs):
2222
"""
2323
#unpack and update the options
2424
ops = du.default_draw_options()
25-
for key, value in kwargs.iteritems():
25+
for key, value in kwargs.items():
2626
ops.update({key:value})
2727
#return ops
2828
width = ops['width']
@@ -63,8 +63,8 @@ def animateModel(model, startDtime=None, endDtime=None, **kwargs):
6363
if userStartDT < simStartDT or userEndDT > simEndDT or timeStepMod != 0 or userEndDT < userStartDT:
6464
#user has entered fault date times either by not being within the
6565
#availble data in the rpt or by starting at something that doesn't fit the timestep
66-
print "PROBLEM WITH DATETIME ENTERED. Make sure it fits within data and start time rest on factor of timestep in minutes."
67-
print "userStartDT = ", userStartDT, "\nuserEndDT = ", userEndDT, "\nsimStartDT = ", simStartDT, "\nsimEndDT = ", simEndDT, "\nTIMESTEP = ", rpt.timeStepMin
66+
print("PROBLEM WITH DATETIME ENTERED. Make sure it fits within data and start time rest on factor of timestep in minutes.")
67+
print("userStartDT = ", userStartDT, "\nuserEndDT = ", userEndDT, "\nsimStartDT = ", simStartDT, "\nsimEndDT = ", simEndDT, "\nTIMESTEP = ", rpt.timeStepMin)
6868
return None
6969

7070
currentT = datetime.strptime(startDtime, "%b-%d-%Y %H:%M:%S") #SWMM dtime format needed
@@ -81,7 +81,7 @@ def animateModel(model, startDtime=None, endDtime=None, **kwargs):
8181
if not os.path.isfile(byteLocDictionaryFName):
8282

8383
#this is a heavy operation, allow a few minutes
84-
print "generating byte dictionary..."
84+
print("generating byte dictionary...")
8585
#conduitByteLocationDict = rpt.createByteLocDict("Link Results")
8686
rpt.createByteLocDict("Link Results")
8787
rpt.createByteLocDict("Node Results")
@@ -96,7 +96,7 @@ def animateModel(model, startDtime=None, endDtime=None, **kwargs):
9696
rpt.elementByteLocations = pickle.load( open(byteLocDictionaryFName, 'r') )
9797
#rpt.byteLocDict = conduitByteLocationDict
9898

99-
print "Started Drawing at " + strftime("%b-%d-%Y %H:%M:%S")
99+
print("Started Drawing at " + strftime("%b-%d-%Y %H:%M:%S"))
100100
log = "Started Drawing at " + strftime("%b-%d-%Y %H:%M:%S") + "\n\nErrors:\n\n"
101101
drawCount = 0
102102
conduitErrorCount = 0
@@ -116,7 +116,7 @@ def animateModel(model, startDtime=None, endDtime=None, **kwargs):
116116

117117
#DRAW THE CONDUITS
118118
if ops['conduitSymb']:
119-
for id, conduit in conduitDicts.iteritems():
119+
for id, conduit in conduitDicts.items():
120120
#coordPair = coordPairDict['coordinates']
121121
if conduit.coordinates: #this prevents draws if no flow is supplied (RDII and such)
122122

@@ -125,11 +125,11 @@ def animateModel(model, startDtime=None, endDtime=None, **kwargs):
125125

126126
drawCount += 1
127127

128-
if drawCount > 0 and drawCount % 2000 == 0: print str(drawCount) + " pipes drawn - simulation time = " + currentTstr
128+
if drawCount > 0 and drawCount % 2000 == 0: print(str(drawCount) + " pipes drawn - simulation time = " + currentTstr)
129129

130130
#DRAW THE NODES
131131
if ops['nodeSymb']:
132-
for id, node in nodeDicts.iteritems():
132+
for id, node in nodeDicts.items():
133133
if node.coordinates: #this prevents draws if no flow is supplied (RDII and such)
134134
su.drawNode(node, nodeDict, draw, rpt=rpt, dTime=currentTstr, options=ops['nodeSymb'], xplier=xplier)
135135
drawCount += 1
@@ -153,7 +153,7 @@ def animateModel(model, startDtime=None, endDtime=None, **kwargs):
153153
imgPath = os.path.join(tempImgDir, image)
154154
frames.append(Image.open(imgPath))
155155

156-
print "building gif with " + str(len(glob.glob1(tempImgDir, "*.png"))) + " frames..."
156+
print("building gif with " + str(len(glob.glob1(tempImgDir, "*.png"))) + " frames...")
157157
if not imgName: imgName = inp.name
158158
gifFile = os.path.join(imgDir, imgName) + ".gif"
159159
frameDuration = 1.0 / float(ops['fps'])
@@ -165,7 +165,7 @@ def animateModel(model, startDtime=None, endDtime=None, **kwargs):
165165
with open(os.path.join(imgDir, "log.txt"), 'w') as logFile:
166166
logFile.write(log)
167167

168-
print "Draw Count =" + str(drawCount)
169-
print "Video saved to:\n\t" + gifFile
168+
print("Draw Count =" + str(drawCount))
169+
print("Video saved to:\n\t" + gifFile)
170170

171171
os.startfile(gifFile)#this doesn't seem to work

swmmio/graphics/drawing.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ def annotate_streets(df, img, text_col):
136136

137137
#confirm font file location
138138
if not os.path.exists(config.font_file):
139-
print 'Error loading defautl font. Check your config.font_file'
139+
print('Error loading defautl font. Check your config.font_file')
140140
return None
141141

142142
unique_sts = df[text_col].unique()
@@ -244,13 +244,13 @@ def _annotateMap (canvas, model, model2=None, currentTstr = None, options=None,
244244
#Buid the title and files list (handle 1 or two input models)
245245
#this is hideous, or elegant?
246246
files = title = results_string = symbology_string = annotationTxt = ""
247-
files = '\n'.join([m.rpt.path for m in filter(None, [model, model2])])
248-
title = ' to '.join([m.inp.name for m in filter(None, [model, model2])])
249-
symbology_string = ', '.join([s['title'] for s in filter(None, [nodeSymb, conduitSymb, parcelSymb])])
247+
files = '\n'.join([m.rpt.path for m in [_f for _f in [model, model2] if _f]])
248+
title = ' to '.join([m.inp.name for m in [_f for _f in [model, model2] if _f]])
249+
symbology_string = ', '.join([s['title'] for s in [_f for _f in [nodeSymb, conduitSymb, parcelSymb] if _f]])
250250
title += "\n" + symbology_string
251251

252252
#collect results
253-
for result, value in results.iteritems():
253+
for result, value in results.items():
254254
results_string += '\n' + result + ": " + str(value)
255255

256256
#compile the annotation text

0 commit comments

Comments
 (0)