Skip to content

Commit

Permalink
Starting to implement global wave watch forecast and Codacy cleanup
Browse files Browse the repository at this point in the history
  • Loading branch information
abkfenris committed Jan 11, 2019
1 parent a88a058 commit 55a429c
Show file tree
Hide file tree
Showing 10 changed files with 55 additions and 37 deletions.
5 changes: 5 additions & 0 deletions .codacy.yaml
Original file line number Diff line number Diff line change
@@ -1,2 +1,7 @@
engines:
prospector:
enabled: true
python_version: 3

exclude_paths:
- "app/deployments/migrations/**.py"
4 changes: 2 additions & 2 deletions Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ Therefore when you are done, `ctrl-c` out of the logs and run `make down` to shu

### Forecasts

See [forecasts/Readme.md](forecasts/Readme.md) for details about how the forecasts API works and how to add new forecasts.
See [forecasts/Readme.md](app/forecasts/Readme.md) for details about how the forecasts API works and how to add new forecasts.

### Adding / Editing Platforms

Expand Down Expand Up @@ -123,7 +123,7 @@ You can use Django fixtures to quickly save models from the database and reload
- `app/`
- `account/` Django user account app.
- `buoy_barn/` Primary Django application.
- `deployments/` Database models and API.
- `deployments/` Database models and API
- `forecasts/` Forecast models and API
- `utils/`
- `wait-for-it.sh` Shell script that can wait until specified services are avaliable before finishing. Helps `make up` launch Django more reliably.
Expand Down
3 changes: 0 additions & 3 deletions app/forecasts/admin.py

This file was deleted.

3 changes: 3 additions & 0 deletions app/forecasts/forecasts/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,14 @@
GFSWindDirection,
)

# from forecasts.forecasts.coastwatch_erddap.wave_watch import GlobalWaveWatchHeight

forecast_list = [
BedfordWaveDirection(),
BedfordWaveHeight(),
BedfordWavePeriod(),
GFSAirTemp(),
GFSWindSpeed(),
GFSWindDirection(),
# GlobalWaveWatchHeight(),
]
28 changes: 10 additions & 18 deletions app/forecasts/forecasts/base_erddap_forecast.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,23 +6,13 @@
# from memoize import memoize
import pandas as pd
import requests
from requests import HTTPError

# from requests import HTTPError

from forecasts.forecasts.base_forecast import BaseForecast
from forecasts.utils import erddap as erddap_utils


# http://www.neracoos.org/erddap/griddap/WW3_72_GulfOfMaine_latest.json?
# hs
# [(2019-01-10T12:00:00Z):1:(2019-01-10T12:00:00Z)]
# [(38.0):1:(46.0)][(-76.0):1:(-60.0)]


# https://coastwatch.pfeg.noaa.gov/erddap/griddap/NCEP_Global_Best.json?
# ugrd10m[(2019-01-07):1:(2019-01-10T12:00:00Z)][(45):1:(45)][(256):1:(256)],
# vgrd10m[(2019-01-07):1:(2019-01-10T12:00:00Z)][(45):1:(45)][(256):1:(256)]


class BaseERDDAPForecast(BaseForecast):
""" Extends BaseForecast with methods for accessing and retrieving forecasts from ERDDAP servers
Expand Down Expand Up @@ -67,7 +57,7 @@ def point_forecast(self, lat: float, lon: float) -> List[Tuple[datetime, float]]
for row in rows
]

def offset_value(self, value: float) -> float:
def offset_value(self, value: float) -> float: # pylint: disable=no-self-use
""" Allows you to override a value to return something more helpful (say Celsius rather than Kelvin) """
return value

Expand Down Expand Up @@ -95,7 +85,7 @@ def dataset_info_df(self) -> pd.DataFrame:
""" Retrieve the most recent metadata for a dataset to find valid time and coordinates
Returns:
Pandas DataFrame
Pandas DataFrame
"""
conn = self.connection()

Expand All @@ -122,7 +112,7 @@ def dataset_query_string(self, lat: float, lon: float) -> str:
lat (float): Latitude in degrees North
lon (float): Longitude in degrees East
Returns:
Returns:
Query string for dataset with variables, times, and coordinates
"""
info_df = self.dataset_info_df()
Expand All @@ -132,8 +122,10 @@ def dataset_query_string(self, lat: float, lon: float) -> str:
for variable in self.request_variables()
)

def coverage_time_str(self, info_df=pd.DataFrame) -> str:
""" Formatted query string element for forecast coverage time range
def coverage_time_str(
self, info_df=pd.DataFrame
) -> str: # pylint: disable=no-self-use
""" Formatted query string element for forecast coverage time range
Args:
info_df (pd.DataFrame): Pandas DataFrame
Expand All @@ -151,7 +143,7 @@ def request_variables(self) -> List[str]:

def coordinates_str(self, info_df: pd.DataFrame, lat: float, lon: float) -> str:
""" Create coordinates query string element
Arguments:
info_df(pd.DataFrame): Dataset metadata DataFrame
lat (float): Latitude in degrees North
Expand Down
11 changes: 5 additions & 6 deletions app/forecasts/forecasts/coastwatch_erddap/gfs.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
from dataclasses import dataclass
from datetime import datetime
from math import degrees, hypot, sin, sqrt
from math import degrees, hypot, sin
from typing import List, Tuple

from forecasts.forecasts.base_forecast import ForecastTypes
from forecasts.forecasts.coastwatch_erddap.base_coastwatch import (
BaseCoastWatchRDDAPForecast,
)
from forecasts.utils import erddap as erddap_utils


class BaseGFSForecast(BaseCoastWatchRDDAPForecast):
Expand All @@ -32,7 +31,7 @@ def offset_value(self, value: float) -> float:

@dataclass
class WindReading:
""" Class for a wind measurement at a given time
""" Class for a wind measurement at a given time
Attributes:
time (datetime): Time of forecasted value
Expand Down Expand Up @@ -70,7 +69,7 @@ def request_variables(self) -> List[str]:
return [self.east_wind_field, self.north_wind_field]

def time_series(self, lat: float, lon: float) -> List[WindReading]:
""" Return a list of WindReadings for a given lat, lon forecast point
""" Return a list of WindReadings for a given lat, lon forecast point
Args:
lat (float): Latitude in degrees North
Expand Down Expand Up @@ -102,7 +101,7 @@ class GFSWindSpeed(BaseGFSWindForecast):
forecast_type = ForecastTypes.WIND_SPEED

def point_forecast(self, lat: float, lon: float) -> List[Tuple[datetime, float]]:
""" Return a list of tuples for the wind speed
""" Return a list of tuples for the wind speed
Args:
lat (float): Latitude in degrees North
Expand All @@ -121,7 +120,7 @@ class GFSWindDirection(BaseGFSWindForecast):

def point_forecast(self, lat: float, lon: float) -> List[Tuple[datetime, float]]:
""" Return a list of tuples for the wind direction
Args:
lat (float): Latitude in degrees North
lon (float): Longitude in degrees East
Expand Down
22 changes: 22 additions & 0 deletions app/forecasts/forecasts/coastwatch_erddap/wave_watch.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
from forecasts.forecasts.base_forecast import ForecastTypes
from forecasts.forecasts.coastwatch_erddap.base_coastwatch import (
BaseCoastWatchRDDAPForecast,
)


class BaseWaveWatch(BaseCoastWatchRDDAPForecast):
dataset = "NWW3_Global_Best"
source_url = "https://coastwatch.pfeg.noaa.gov/erddap/griddap/NWW3_Global_Best.html"

to_360 = True


class GlobalWaveWatchHeight(BaseWaveWatch):
slug = "global_wave_watch_height"
name = "Global Wave Watch III - Significant Wave Height"
description = (
"Wave Height from the Global Wave Watch III model by the University of Hawaii"
)
forecast_type = ForecastTypes.WAVE_HEIGHT

field = "Thgt"
3 changes: 0 additions & 3 deletions app/forecasts/models.py

This file was deleted.

2 changes: 1 addition & 1 deletion app/forecasts/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@


class ForecastSerializer(serializers.BaseSerializer):
def to_representation(self, obj):
def to_representation(self, obj): # pylint: disable=no-self-use

return {
"slug": obj.slug,
Expand Down
11 changes: 7 additions & 4 deletions app/forecasts/views.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from rest_framework import viewsets
from rest_framework.decorators import action
from rest_framework.exceptions import NotFound
from rest_framework.response import Response

from forecasts.forecasts import forecast_list
Expand All @@ -9,13 +9,16 @@
class ForecastViewSet(viewsets.ViewSet):
""" A viewset for forecasts """

def list(self, request):
def list(self, request): # pylint: disable=no-self-use
serializer = ForecastSerializer(forecast_list, many=True)
return Response(serializer.data)

def retrieve(self, request, pk=None):
def retrieve(self, request, pk=None): # pylint: disable=no-self-use
filtered = [forecast for forecast in forecast_list if forecast.slug == pk]
forecast = filtered[0]
try:
forecast = filtered[0]
except IndexError:
raise NotFound(detail=f"Unknown forecast slug: {pk}")
seralizer = ForecastSerializer(forecast)
data = seralizer.data

Expand Down

0 comments on commit 55a429c

Please sign in to comment.