-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathreturn_periods.py
167 lines (142 loc) · 7.41 KB
/
return_periods.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
# Culvert max return periods
# David Gold
# June 9 2015
#
# Edits made by Noah Warnke 2016
# Updated by Lisa Watkins 9/15/2016
#
# Some comments added by Tanvi Naidu 6/14/2017
#
# Given culvert capacity and peak discharge from storm events, determine the
# highest return period storm that a culvert can pass for current and future rainfall conditions.
import numpy, os, re, csv, loader
#Imports required packages and modules and the function loader which was written
#by Noah in 2016 and saved as loader.py
#(loader organizes the data from input file based on headers defined in a signature)
def return_periods(capacity_filename, current_runoff_filename, future_runoff_filename, return_periods_output_filename, final_output_filename):
# 1st Signature: Runoff signature:
# This creates a list of dictionaries that stores the relevant headers of
# the input file and the type of data in the column under that header
runoff_signature = [
{'name': 'BarrierID', 'type': str},
#eg: The first element of the list 'runoff_signature' is a dictionary for barrier id.
#'BarrierID' is the header of a column of data we want to extract from the input file,containing
#data of type strings
{'name': 'Area_sqkm', 'type': float},
# Later: NEW_Lat, NEW_Long
{'name': 'Tc_hr', 'type': float},
{'name': 'CN', 'type': float},
{'name': 'Y1', 'type': float},
{'name': 'Y2', 'type': float},
{'name': 'Y5', 'type': float},
{'name': 'Y10', 'type': float},
{'name': 'Y25', 'type': float},
{'name': 'Y50', 'type': float},
{'name': 'Y100', 'type': float},
{'name': 'Y200', 'type': float},
{'name': 'Y500', 'type': float}
]
# 2nd Signature: Culvert signature:
culvert_signature = [
{'name': 'BarrierID', 'type': str},
{'name': 'NAACC_ID', 'type': int},
{'name': 'Lat', 'type': float},
{'name': 'Long', 'type': float},
{'name': 'Q', 'type': float},
{'name': 'Flags', 'type': int},
{'name': 'Comments', 'type': str},
{'name': 'Culvert_Area', 'type': float},
]
# Load and validate current and future runoffs:
# current_runoff_data will now store the relevant data from the current runoff input file
# in the format described in loader.py using the first signature defined above.
# valid_rows will store all value for the key 'valid_rows' in the dictionary current_runoff_data
current_runoff_data = loader.load(current_runoff_filename, runoff_signature, 1, -1)
current_runoff_rows = current_runoff_data['valid_rows']
future_runoff_data = loader.load(future_runoff_filename, runoff_signature, 1, -1)
future_runoff_rows = future_runoff_data['valid_rows']
# Create lookup dictionaries for the runoffs. This speeds matching culverts to watersheds up quite a bit.
current_runoff_lookup = {}
for watershed in current_runoff_rows:
current_runoff_lookup[watershed['BarrierID']] = watershed
future_runoff_lookup = {}
for watershed in future_runoff_rows:
future_runoff_lookup[watershed['BarrierID']] = watershed
# Load culvert capacities:
culvert_data = loader.load(capacity_filename, culvert_signature, 1, -1)
culvert_rows = culvert_data['valid_rows']
# A list of the years.
years = [0, 1, 2, 5, 10, 25, 50, 100, 200, 500]
# A helper function to find the first overflow.
def find_first_overflow(culvert, watershed, years):
capacity = culvert['Q']
#stores the max flow in culvert as 'capacity'
i = 1
while i < len(years):
year = years[i]
#loops through all the relevant return periods
if capacity < watershed['Y' + str(year)]:
return years[i - 1]
#if capacity is lower than the runoff for a particular return period,
# return the previous highest return period.
i += 1
return years[i - 1]
# Compute which return period each culvert will be able to withstand.
for culvert in culvert_rows:
# Find the corresponding current and future watersheds (they share BarrierID):
culvert['watershed'] = None
try:
current_watershed = current_runoff_lookup[culvert['BarrierID']]
future_watershed = future_runoff_lookup[culvert['BarrierID']]
culvert['current_return'] = find_first_overflow(culvert, current_watershed, years)
#returns the highest withstandable return period for current storm data
culvert['future_return'] = find_first_overflow(culvert, future_watershed, years)
#returns the highest withstandable return period for future storm data
culvert['watershed'] = current_watershed # Also save the watershed info, since we'll want it for our final output.
if culvert['Flags'] == 0:
culvert['Flags'] = 1 # Also fix flags so it means number of culverts (previously, flag '0' meant 1 culvert)
except KeyError:
print "Did not find watershed for barrierID " + culvert['BarrierID']
# Did not find a watershed corresponding to this culvert in the runoffs. Skip.
# TODO export skipped culverts.
continue
# Just save the return periods.
with open(return_periods_output_filename, 'wb') as return_output_file:
csv_writer = csv.writer(return_output_file)
# Header
csv_writer.writerow(['BarrierID','Current Max Return (yr)','Future Max Return (yr)'])
# Each row.
for culvert in culvert_rows:
watershed = culvert['watershed']
if watershed == None:
continue # Skip all the culverts we couldn't match with watersheds.
csv_writer.writerow([culvert['BarrierID'], culvert['current_return'], culvert['future_return']])
# Now save all the final data (easier to do that here since all the relevant files are already open.)
with open(final_output_filename, 'wb') as final_output_file:
csv_writer = csv.writer(final_output_file)
# Header
csv_writer.writerow(['BarrierID', 'NAACC_ID', 'Original Latitude', 'Original Longitude', 'Point Moved', 'New Latitude', 'New Longitude', 'Current Max Return Period (yr)', 'Future Max Return Period (yr)', 'Capacity (m^3/s)', 'Cross sectional Area (m^2)', 'WS Area (sq km)', 'Tc (hr)', 'CN', 'Number of Culverts', 'Comments'])
# Each row.
for culvert in culvert_rows:
watershed = culvert['watershed']
if watershed == None:
print "Skipping culvert " + culvert['BarrierID']
continue # Skip all the culverts we couldn't match with watersheds.
csv_writer.writerow([
culvert['BarrierID'], \
culvert['NAACC_ID'], \
culvert['Lat'], \
culvert['Long'], \
"?", \
"?", \
"?", \
culvert['current_return'], \
culvert['future_return'], \
culvert['Q'], \
culvert['Culvert_Area'], \
watershed['Area_sqkm'], \
watershed['Tc_hr'], \
watershed['CN'], \
culvert['Flags'], \
culvert['Comments']
])