Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feedback #1

Open
wants to merge 66 commits into
base: feedback
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
66 commits
Select commit Hold shift + click to select a range
62fbf2b
Setting up GitHub Classroom Feedback
github-classroom[bot] Jan 24, 2021
4d92adb
Test Commit (lk480)
lk480 Jan 24, 2021
793f10c
Corrected flake8 stylistic error
lk480 Jan 24, 2021
81b82a8
Corrected 2nd flake8 error
lk480 Jan 24, 2021
a62d3d7
Added a help-guide to get started with IDE/Git/Linting
lk480 Jan 24, 2021
54c2eec
Implemented stations_by_distance function.
lk480 Jan 24, 2021
0478fab
Corrected Docstring for sorted_by_key
lk480 Jan 24, 2021
ab1f8ed
Merge branch 'main' of https://github.com/cued-ia-computing/flood-jzo…
lk480 Jan 24, 2021
17ad092
Completed Task 1B demo and implemented a test for stations_by_distance.
lk480 Feb 1, 2021
6d241ce
Added haversine to setup.py for pytest.
lk480 Feb 1, 2021
83b88bb
Added haversine to install dependencies
lk480 Feb 1, 2021
31e4441
Merge pull request #2 from cued-ia-computing/lk480_task1b
lk480 Feb 1, 2021
85e68ea
Added river_by_station_number function and added mock classes for tes…
lk480 Feb 6, 2021
431d4c6
Added Mock to ci config for testing
lk480 Feb 6, 2021
d180a6d
Added mock to github ci workflow config
lk480 Feb 6, 2021
1d7efd5
Added comments to rivers_by_station_number function and tided up vari…
lk480 Feb 6, 2021
00d088c
Completed demonstration programme for Task 1E
lk480 Feb 6, 2021
6c8d12c
Fixed ineqaulity error in rivers_by_station_number
lk480 Feb 6, 2021
89f6441
Added tests to check rivers_by_station function
lk480 Feb 6, 2021
e50bfd8
Merge pull request #3 from cued-ia-computing/lk480_task_1E
lk480 Feb 6, 2021
2d23a01
jzo20_1C
JiaZhengOng Feb 6, 2021
7240f64
Added range consistency checks to station.py with associated tests
lk480 Feb 6, 2021
21ec1a5
Completed Task 1F Demonstration Program
lk480 Feb 6, 2021
e3abfcc
Merge pull request #4 from cued-ia-computing/lk480_task_1F
lk480 Feb 6, 2021
8228c84
Added docstrings to geo.py function
lk480 Feb 6, 2021
b525ceb
Added docstrings to station.py methods/functions
lk480 Feb 6, 2021
f8a440e
Merge pull request #5 from cued-ia-computing/lk480_docstrings
lk480 Feb 6, 2021
f3315e6
Finished 1C
JiaZhengOng Feb 9, 2021
333e6e4
Fixed assertion error due to generator object
lk480 Feb 9, 2021
981b99f
competed 1D
JiaZhengOng Feb 9, 2021
e3c1a2b
update 1C
JiaZhengOng Feb 9, 2021
0cc6676
update 1C
JiaZhengOng Feb 9, 2021
e84d07f
Merge origin/main' into jzo20_1C
lk480 Feb 9, 2021
39002dc
Merge pull request #6 from cued-ia-computing/jzo20_1C
lk480 Feb 9, 2021
8cb9a4b
Merge remote 'origin/main' into jzo20_1D
lk480 Feb 9, 2021
b016b80
Merge pull request #7 from cued-ia-computing/jzo20_1D
lk480 Feb 9, 2021
f83caa1
added missing doc strings
lk480 Feb 9, 2021
1493cee
Merge pull request #8 from cued-ia-computing/add_missing_doc_strimgs
lk480 Feb 9, 2021
86af832
Completed Demo Program for Task 1B
lk480 Feb 20, 2021
d5bcb24
Completed Task 2B
lk480 Feb 20, 2021
330d57f
Merge pull request #9 from cued-ia-computing/lk480_Task2B
lk480 Feb 20, 2021
2ff48f2
Completed Task 2E
lk480 Feb 20, 2021
b77b660
Merge pull request #10 from cued-ia-computing/lk480_Task2C
lk480 Feb 20, 2021
0453e36
Partially Completed Task 2F - waiting on Task 2C
lk480 Feb 20, 2021
25f8471
Task 2C
JiaZhengOng Feb 26, 2021
3dfcf62
small modification on 2C
JiaZhengOng Feb 27, 2021
75fc01a
small modification on error lint with flake8
JiaZhengOng Feb 27, 2021
5c7ec99
stations_highest_rel_level to use function from 2B
lk480 Feb 28, 2021
29ad76b
Merge pull request #11 from cued-ia-computing/jzo20_Task2C
lk480 Feb 28, 2021
fd58f6b
Merge remote-tracking branch 'origin/main' into lk480_Task2F
lk480 Feb 28, 2021
8636da8
Completed Task 2F
lk480 Feb 28, 2021
6eaffb8
Merge pull request #12 from cued-ia-computing/lk480_Task2F
lk480 Feb 28, 2021
1e7b4cb
Completed 2G
lk480 Mar 3, 2021
b024e16
Merge pull request #13 from cued-ia-computing/Task_2G
lk480 Mar 3, 2021
29215ae
Added a func to filter extreme value
JiaZhengOng Mar 3, 2021
0905a97
Modify 2C
JiaZhengOng Mar 3, 2021
dfeaa91
Define a new class for 2G
JiaZhengOng Mar 3, 2021
588e12d
Modify the extreme value filter
JiaZhengOng Mar 3, 2021
d8772ab
Completed 2G
JiaZhengOng Mar 3, 2021
f200d30
Merge branch 'jzo20_2G'
JiaZhengOng Mar 3, 2021
8bfd03b
minor changes
lk480 Mar 3, 2021
06cda25
Merge remote-tracking branch 'origin/Task_2G' into main
lk480 Mar 3, 2021
ea119be
final commit for submission
lk480 Mar 3, 2021
1eaa540
Merge pull request #14 from cued-ia-computing/milestone2
lk480 Mar 3, 2021
0235125
Corrected Task 2E and 2F (#15)
lk480 Mar 3, 2021
6de96e0
Corrections (#16)
lk480 Mar 4, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/pythonapp.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ jobs:
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install flake8 matplotlib pytest requests
pip install flake8 matplotlib pytest requests haversine mock

- name: Lint with flake8
run: flake8 --statistics *.py
Expand Down
20 changes: 10 additions & 10 deletions .gitlab-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,18 @@ image: python:3.7

test:
script:
# Install Python packages required to run code. Add any additional
# packages your code needs require here.
- pip install dateutils flake8 matplotlib numpy pytest requests
# Install Python packages required to run code. Add any additional
# packages your code needs require here.
- pip install dateutils flake8 matplotlib numpy pytest requests mock

# flake8 static code and style testing. Enable for extra testing.
# - python -m flake8 .
# flake8 static code and style testing. Enable for extra testing.
# - python -m flake8 .

# Run unit tests
- python -m pytest -v .
- python -m pytest -v .

# Run deliverables. Add your deliverables to the test system here.
- python Task1A.py
# Run deliverables. Add your deliverables to the test system here.
- python Task1A.py

- python Task2A.py
- python Task2D.py
- python Task2A.py
- python Task2D.py
60 changes: 60 additions & 0 deletions Help-Guide.rtf
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
{\rtf1\ansi\ansicpg1252\cocoartf2577
\cocoatextscaling0\cocoaplatform0{\fonttbl\f0\fnil\fcharset0 Menlo-Regular;}
{\colortbl;\red255\green255\blue255;\red0\green0\blue0;\red255\green255\blue255;\red27\green31\blue34;
\red10\green77\blue204;\red249\green250\blue251;}
{\*\expandedcolortbl;;\cssrgb\c0\c0\c0;\cssrgb\c100000\c100000\c100000;\cssrgb\c14118\c16078\c18039;
\cssrgb\c1176\c40000\c83922;\cssrgb\c98039\c98431\c98824;}
\paperw11900\paperh16840\margl1440\margr1440\vieww11520\viewh8400\viewkind0
\pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\pardirnatural\partightenfactor0

\f0\fs28 \cf2 \cb3 CUED Flood Warning System:\
\
Creating SSH Key: (Recommended but not mandatory)\
\
1. Check for existing SSH Keys - \
\pard\pardeftab720\partightenfactor0
\cf2 \expnd0\expndtw0\kerning0
ls -al ~/.ssh\
# Lists the files in your .ssh directory, if they exist\
\
2. \
ssh-keygen -t ed25519 -C "your_email@example.com"\
\
3. Changing Passphrase\
ssh-keygen -p -f ~/.ssh/id_ed25519\
\
Git:\
\
1. Use source control to manage commits, messages and pushing to repo.\
\
2. To push change:\
\
- Head to source control \
- View proposed change\
- Click on \'91stage change\'92 icon\
- Add commit message\
- Click check mark to commit (to local file system)\
- Click (\'85) to view further options and select push (sends to remote team repo.)\
\
Linting:\
\
1. Open terminal: pip install pylint (\'97-user) \
\
2. Open command palette on VSCode\
\
3. Type - Python: Select Linter\
\
4. Choose flake8 (a wrapper which checks code for adherence to flake8 coding style)\
\
\
5. GitHub Build Log (under Actions) shows potential errors with commits to repo including stylistic errors. \
\
6. Please use clear messages when committing to repo for benefit of other team members.\
\
7. Commit - Saves to local file system. \
Push - Pushes changes to GitHub remote repo. ({\field{\*\fldinst{HYPERLINK "https://github.com/cued-ia-computing/flood-jzo20-lk480"}}{\fldrslt \cf5 \cb6 flood-jzo20-lk480}}\cf4 \cb1 )
\fs27\fsmilli13600 \cf2 \cb3 \
\
\
\
}
19 changes: 19 additions & 0 deletions Task1B.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
from floodsystem.stationdata import build_station_list
from floodsystem.geo import stations_by_distance


def run():

station = build_station_list()
list_of_stations = stations_by_distance(station, (52.2053, 0.1218))
ten_closest_stations = [(station.name, station.town, distance) for station, distance in list_of_stations[:10]]
ten_furthest_stations = [(station.name, station.town, distance) for station, distance in list_of_stations[-10:]]
print(f"10 closest stations from cambridge \n: {ten_closest_stations}")
print(f"10 furthest stations from cambridge \n: {ten_furthest_stations}")


if __name__ == "__main__":
print("*** Task 1B: CUED Part IA Flood Warning System ***")
run()

my_variable = 8
18 changes: 18 additions & 0 deletions Task1C.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
from floodsystem.stationdata import build_station_list
from floodsystem.geo import stations_within_radius


def run():

stations = build_station_list()
centre_coord = (52.2053, 0.1218)
r = 10
list_of_stations = stations_within_radius(stations, centre_coord, r)
print("All stations within {rad}km from {centre}\n: {ans}".format(rad=r, centre=centre_coord, ans=list_of_stations))


if __name__ == "__main__":
print("*** Task 1C: CUED Part IA Flood Warning System ***")
run()

my_variable = 8
39 changes: 39 additions & 0 deletions Task1D.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
from floodsystem.stationdata import build_station_list
from floodsystem.geo import rivers_with_station
from floodsystem.geo import stations_by_river


def run():
# Build the MoniteringStation list
stations = build_station_list()

# Part 1, first 10 river with at least one station
num_station_atleast_one = rivers_with_station(stations)
first_ten = num_station_atleast_one[:10]
# printing the length and first 10
print('{} stations. First 10 - {}'.format(len(num_station_atleast_one), first_ten))

# Part 2
Obj_around_river = stations_by_river(stations)
Aire = sorted(Obj_around_river['River Aire'])
Cam = sorted(Obj_around_river['River Cam'])
Thames = sorted(Obj_around_river['River Thames'])
print('River Aire stations: {}\n River Cam stations: {}\n River Thames stations: {}\n'.format(Aire, Cam, Thames))

# Without getting a dictionary
# for river in ["River Aire", "River Cam", "River Thames"]:
# station_list = []

# for station in stations_by_river(stations)[river]: (couldn't work)

# for station in stations: (but this works)
# if river == station.river:
# station_list.append(station.name)
# print(sorted(station_list))


if __name__ == "__main__":
print("*** Task 1D: CUED Part IA Flood Warning System ***")
run()

my_variable = 8
14 changes: 14 additions & 0 deletions Task1E.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
from floodsystem.stationdata import build_station_list
from floodsystem.geo import rivers_by_station_number


def run():
N = 9 # As stated in demonstration program requirements
stations = build_station_list()
result = rivers_by_station_number(stations, N)
print(f"List of {N} rivers with the greatest number of monitoring stations \n {result}")


if __name__ == "__main__":
print("*** Task 1E: CUED Part IA Flood Warning System ***")
run()
13 changes: 13 additions & 0 deletions Task1F.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
from floodsystem.stationdata import build_station_list
from floodsystem.station import inconsistent_typical_range_stations


def run():
stations = build_station_list()
result = inconsistent_typical_range_stations(stations)
print(f"List of stations with inconsistent typical range data \n {result}")


if __name__ == "__main__":
print("*** Task 1F: CUED Part IA Flood Warning System ***")
run()
21 changes: 21 additions & 0 deletions Task2B.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
from floodsystem.stationdata import build_station_list, update_water_levels
from floodsystem.flood import stations_level_over_threshold


def run():
# Build list of stations
stations = build_station_list()

# Update latest level data for all stations
update_water_levels(stations)

# Obtain list of stations with relative level over given threshold
result = stations_level_over_threshold(stations, 0.8)

for station, relative_level in result:
print(f"{station.name}: {relative_level}")


if __name__ == "__main__":
print("*** Task 2B: CUED Part IA Flood Warning System ***")
run()
21 changes: 21 additions & 0 deletions Task2C.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
from floodsystem.stationdata import build_station_list, update_water_levels
from floodsystem.flood import stations_highest_rel_level


def run():
# Build list of stations
stations = build_station_list()

# Update latest level data for all stations
update_water_levels(stations)

# Obtain list of stations with highest relative water level
result = stations_highest_rel_level(stations, 10)

for station, relative_level in result:
print(f"{station.name}: {relative_level}")


if __name__ == "__main__":
print("*** Task 2C: CUED Part IA Flood Warning System ***")
run()
20 changes: 20 additions & 0 deletions Task2E.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
from floodsystem.stationdata import build_station_list, get_historical_water_levels
from floodsystem.plot import plot_water_levels, plot_water_levels_bokeh


def run(plot_type):
# Build list of stations
stations = build_station_list()
station = stations[0]
dates, levels = get_historical_water_levels(station, 10)
if plot_type == "matplotlib":
plot_water_levels(station, dates, levels)
elif plot_type == "bokeh":
plot_water_levels_bokeh(station, dates, levels)
else:
raise Exception(f"Unknown Plot Type {plot_type}")


if __name__ == "__main__":
print("*** Task 2E: CUED Part IA Flood Warning System ***")
run("matplotlib")
20 changes: 20 additions & 0 deletions Task2F.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
from floodsystem.stationdata import build_station_list, update_water_levels, get_historical_water_levels
from floodsystem.plot import plot_water_level_with_fit
from floodsystem.flood import stations_highest_rel_level


def run():
# Build list of stations
stations = build_station_list()
# Update latest level data for all stations
update_water_levels(stations)

stations_highest_level = stations_highest_rel_level(stations, 5)
for station, _ in stations_highest_level:
dates, levels = get_historical_water_levels(station, 2)
plot_water_level_with_fit(station, dates, levels, 4)


if __name__ == "__main__":
print("*** Task 2F: CUED Part IA Flood Warning System ***")
run()
17 changes: 17 additions & 0 deletions Task2G.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Flood Warning System Flood Risk Assesment Methodology

This file outline the assesment methodology for determining the flood risk at towns across the UK.

Polynomial Regression:
To generate a regression line to forecast future water levels we utilised numpy polyfit.
The numpy.poly1d object allows us to obtain the latest water level according to the polynimal regression
line on the day we have specified.

The polynomial is generated by using a least-squares regression on a set period of historical data. After
experimenting with different lookback periods, 30 days gave us the most accurate forecast and hence is the default argument to the function.

Assesment:
To classify the towns for flood risk we utilised the relative water level to compare the latest forecasted level to
the typical high/low range data for each station. We then sorted the stations by the town they were situated in and selected the largest relative water level.

We then utilised a conditional statement to classify the risk level depending on the magnitude of the relative water level. Thus obtaining a flood risk assesment for all towns in the DEFRA.
77 changes: 77 additions & 0 deletions Task2G.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
from datetime import date
from collections import defaultdict
from floodsystem.stationdata import build_station_list, update_water_levels
from floodsystem.analysis import update_forecasted_levels
from floodsystem.flood import stations_highest_rel_level

# Please see classification methodology .md file

SEVERE = 2.0
HIGH = 1.0
MODERATE = 0.5
LOW = 0.0


def risk_assesment(relative_water_levels):
"""Takes a list of relative water levels by station for each town, computes the
largest relative water level.
If largest relative water level is greater than [2.0,] returns Severe.
If largest relative water level is between than [1.0, 2.0), returns High.
If largest relative water level is between than [0.5, 1.0), returns Moderate.
If largest relative water level is greater than [, 0.5), returns Severe.
Args:
relative_water_levels ([list]): List of relative water levels
Returns:
[str]: Flood Risk Assesment
"""
max_relative_water_level = max([x for x in relative_water_levels if x is not None])
if max_relative_water_level >= SEVERE:
return 'Severe'
elif HIGH <= max_relative_water_level < SEVERE:
return 'High'
elif MODERATE <= max_relative_water_level < HIGH:
return 'Moderate'
else:
return 'Low'


def run(forecast_date, N=50):
# 1. Build list of all Monitoring Stations
all_stations = build_station_list()
# 2. Update latest water levels for each station
update_water_levels(all_stations)
# 3. Find N stations with highest latest water level
stations_rel_level = stations_highest_rel_level(all_stations, N)
# 4. Unpack list of station objects
stations = [station for station, _ in stations_rel_level]
# 5. Forecast level for given date and update the latest-level for each station
update_forecasted_levels(stations, forecast_date)
# 6. Create default dictionary with values of an empty list
relative_levels_by_town = defaultdict(list)

# 7. Populating relative_levels_town with relative water level for each station in a town
for station in stations:
# Exclude stations where the town name is not provided
if station.town is not None:
v = relative_levels_by_town[station.town]
v.append(station.relative_water_level())

# 8. Create dictionary to store flood warning by town
flood_warning_by_town = {}

# 9. Populate dictionary by calling risk_assesment() function with a list of forecasted
# relative water levels.
for town, relative_water_levels in relative_levels_by_town.items():
flood_warning_by_town[town] = risk_assesment(relative_water_levels)

# 10. Return dictionary of flood warning by town
return flood_warning_by_town


if __name__ == "__main__":
print("*** Task 2G: CUED Part IA Flood Warning System ***")
forecast_date = date(2021, 3, 5)
number_of_stations = 50
flood_warning_by_town = run(forecast_date, number_of_stations)
for k, v in flood_warning_by_town.items():
print(f"{k}: {v}")
Loading