-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Add country ingestor * Add code to the station * Fix flake * Add Ingestor Session * Add Tahmo ingestor * Add ingestor to worker * Add missing docstring * Disable celery on tests * Rename field * Fix tests
- Loading branch information
Showing
25 changed files
with
687 additions
and
140 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -79,5 +79,6 @@ services: | |
links: | ||
- db | ||
- redis | ||
- worker | ||
- celery_beat | ||
entrypoint: [ ] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
# coding=utf-8 | ||
""" | ||
Tomorrow Now GAP. | ||
.. note:: Project level settings. | ||
""" | ||
|
||
from .prod import * # noqa | ||
|
||
TEST_RUNNER = 'core.tests.runner.CustomTestRunner' | ||
DEBUG = True | ||
|
||
# Disable caching while in development | ||
CACHES = { | ||
'default': { | ||
'BACKEND': 'django.core.cache.backends.dummy.DummyCache', | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
# coding=utf-8 | ||
""" | ||
Tomorrow Now GAP. | ||
.. note:: Test runner. | ||
""" | ||
|
||
from core.celery import app as celery_app | ||
from django.conf import settings | ||
from django.test.runner import DiscoverRunner | ||
|
||
|
||
class CustomTestRunner(DiscoverRunner): | ||
"""Postgres schema test runner.""" | ||
|
||
@staticmethod | ||
def __disable_celery(): | ||
"""Disabling celery.""" | ||
settings.CELERY_BROKER_URL = \ | ||
celery_app.conf.BROKER_URL = 'filesystem:///dev/null/' | ||
celery_app.conf.task_always_eager = True | ||
data = { | ||
'data_folder_in': '/tmp', | ||
'data_folder_out': '/tmp', | ||
'data_folder_processed': '/tmp', | ||
} | ||
settings.BROKER_TRANSPORT_OPTIONS = \ | ||
celery_app.conf.BROKER_TRANSPORT_OPTIONS = data | ||
|
||
def setup_test_environment(self, **kwargs): | ||
"""Prepare test env.""" | ||
CustomTestRunner.__disable_celery() | ||
super(CustomTestRunner, self).setup_test_environment(**kwargs) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
# coding=utf-8 | ||
""" | ||
Tomorrow Now GAP. | ||
.. note:: Exceptions for ingestor. | ||
""" | ||
|
||
|
||
class FileNotFoundException(Exception): | ||
"""File not found.""" | ||
|
||
def __init__(self): # noqa | ||
self.message = 'File not found.' | ||
super().__init__(self.message) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,178 @@ | ||
# coding=utf-8 | ||
""" | ||
Tomorrow Now GAP. | ||
.. note:: Tahmo ingestor. | ||
""" | ||
|
||
import csv | ||
import json | ||
import os | ||
import shutil | ||
from datetime import datetime, timezone | ||
from zipfile import ZipFile | ||
|
||
from django.contrib.gis.geos import Point | ||
|
||
from gap.ingestor.exceptions import FileNotFoundException | ||
from gap.models import ( | ||
Provider, Station, ObservationType, Country, IngestorSession, | ||
Attribute, Measurement | ||
) | ||
|
||
|
||
class TahmoVariable: | ||
"""Contains Tahmo Variable.""" | ||
|
||
def __init__(self, name, unit=None): | ||
"""Initialize the Tahmo variable.""" | ||
self.name = name | ||
self.unit = unit | ||
|
||
|
||
TAHMO_VARIABLES = { | ||
'ap': TahmoVariable('Atmospheric pressure'), | ||
'pr': TahmoVariable('Precipitation', 'mm'), | ||
'rh': TahmoVariable('Relative humidity'), | ||
'ra': TahmoVariable('Shortwave radiation', 'W/m2'), | ||
'te': TahmoVariable('Surface air temperature', '°C'), | ||
'wd': TahmoVariable('Wind direction', 'Degrees from North'), | ||
'wg': TahmoVariable('Wind gust', 'm/s'), | ||
'ws': TahmoVariable('Wind speed', 'm/s') | ||
} | ||
|
||
|
||
class TahmoIngestor: | ||
"""Ingestor for tahmo data.""" | ||
|
||
def __init__(self, session: IngestorSession): | ||
"""Initialize the ingestor.""" | ||
self.session = session | ||
|
||
self.provider, _ = Provider.objects.get_or_create( | ||
name='Tahmo' | ||
) | ||
self.obs_type, _ = ObservationType.objects.get_or_create( | ||
name='Ground Observations' | ||
) | ||
|
||
def _run(self, dir_path): | ||
"""Run the ingestor.""" | ||
# Data is coming from CSV. | ||
# CSV headers: | ||
# - longitude | ||
# - latitude | ||
# - station code | ||
# - name | ||
|
||
# INGEST STATIONS | ||
for (dirpath, dirnames, filenames) in os.walk(dir_path): | ||
for filename in filenames: | ||
try: | ||
reader = csv.DictReader( | ||
open(os.path.join(dirpath, filename), 'r') | ||
) | ||
if 'station' in filename: | ||
for data in reader: | ||
try: | ||
point = Point( | ||
x=float(data['longitude']), | ||
y=float(data['latitude']), | ||
srid=4326 | ||
) | ||
try: | ||
country = Country.get_countries_by_point( | ||
point | ||
)[0] | ||
except IndexError: | ||
country = None | ||
Station.objects.get_or_create( | ||
code=data['station code'], | ||
provider=self.provider, | ||
defaults={ | ||
'name': data['name'], | ||
'geometry': point, | ||
'country': country, | ||
'observation_type': self.obs_type, | ||
} | ||
) | ||
except KeyError as e: | ||
raise Exception( | ||
json.dumps({ | ||
'filename': filename, | ||
'data': data, | ||
'error': f'{e}' | ||
}) | ||
) | ||
except UnicodeDecodeError: | ||
continue | ||
|
||
# INGEST MEASUREMENTS | ||
for (dirpath, dirnames, filenames) in os.walk(dir_path): | ||
for filename in filenames: | ||
code = filename.split('_')[0] | ||
try: | ||
station = Station.objects.get( | ||
code=code, provider=self.provider | ||
) | ||
reader = csv.DictReader( | ||
open(os.path.join(dirpath, filename), 'r') | ||
) | ||
for data in reader: | ||
date = data[''] # noqa | ||
if not date: | ||
continue | ||
date_time = datetime.strptime( | ||
date, '%Y-%m-%d %H:%M' | ||
).replace(tzinfo=timezone.utc) | ||
date_time.replace(second=0) | ||
for key, value in data.items(): # noqa | ||
try: | ||
attr_var = TAHMO_VARIABLES[key] | ||
except KeyError: | ||
continue | ||
try: | ||
attribute, _ = Attribute.objects.get_or_create( | ||
name=attr_var.name | ||
) | ||
try: | ||
unit = attr_var.unit | ||
except KeyError: | ||
unit = None | ||
measure, _ = Measurement.objects.get_or_create( | ||
station=station, | ||
attribute=attribute, | ||
date_time=date_time, | ||
defaults={ | ||
'unit': unit, | ||
'value': float(value) | ||
} | ||
) | ||
except (KeyError, ValueError) as e: | ||
raise Exception( | ||
json.dumps({ | ||
'filename': filename, | ||
'data': data, | ||
'error': f'{e}' | ||
}) | ||
) | ||
except Station.DoesNotExist: | ||
pass | ||
|
||
def run(self): | ||
"""Run the ingestor.""" | ||
if not self.session.file: | ||
raise FileNotFoundException() | ||
|
||
# Extract file | ||
dir_path = os.path.splitext(self.session.file.path)[0] | ||
with ZipFile(self.session.file.path, 'r') as zip_ref: | ||
zip_ref.extractall(dir_path) | ||
|
||
# Run the ingestion | ||
try: | ||
self._run(dir_path) | ||
shutil.rmtree(dir_path) | ||
except Exception as e: | ||
shutil.rmtree(dir_path) | ||
raise Exception(e) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.