Skip to content

Commit 305ddba

Browse files
authored
Merge pull request #36 from OpenGeoscience/udatp
University of Delaware Air Temp and Precipitation Processor
2 parents 6b37452 + 5b0894b commit 305ddba

9 files changed

Lines changed: 377 additions & 3 deletions

File tree

dataqs/helpers.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
import ogr2ogr
3434
import rasterio
3535
from osgeo import gdal, ogr
36+
from osr import SpatialReference
3637
import xml.etree.ElementTree as ET
3738
from StringIO import StringIO
3839
from rasterio.warp import RESAMPLING
@@ -119,9 +120,6 @@ def gdal_translate(src_filename, dst_filename, of="GTiff", bands=None,
119120
Convert a raster image with the specified arguments
120121
(as if running from commandline)
121122
"""
122-
from osgeo import gdal
123-
from osr import SpatialReference
124-
125123
if not options:
126124
options = []
127125

dataqs/udatp/__init__.py

Whitespace-only changes.
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<?xml version="1.0" encoding="UTF-8"?><sld:StyledLayerDescriptor xmlns="http://www.opengis.net/sld" xmlns:sld="http://www.opengis.net/sld" xmlns:ogc="http://www.opengis.net/ogc" xmlns:gml="http://www.opengis.net/gml" version="1.0.0">
2+
<sld:NamedLayer>
3+
<sld:Name>uod_air_mean_401</sld:Name>
4+
<sld:UserStyle>
5+
<sld:Name>uod_air_mean_401</sld:Name>
6+
<sld:Title>uod_air_mean_401</sld:Title>
7+
<sld:FeatureTypeStyle>
8+
<sld:Name>name</sld:Name>
9+
<sld:Rule>
10+
<sld:RasterSymbolizer>
11+
<ColorMap extended="true">
12+
<sld:ColorMapEntry color="#FFFFFF" label="" opacity="0.0" quantity="-999"/>
13+
<sld:ColorMapEntry color="#2b83ba" label="&lt;= -30 °C" opacity="1.0" quantity="-30"/>
14+
<sld:ColorMapEntry color="#6bb0af" label="-20.0 °C" opacity="1.0" quantity="-20"/>
15+
<sld:ColorMapEntry color="#abdda4" label="-10.0 °C" opacity="1.0" quantity="-10"/>
16+
<sld:ColorMapEntry color="#d5eeb1" label="-5.0 °C" opacity="1.0" quantity="-5"/>
17+
<sld:ColorMapEntry color="#ffffbf" label="0 °C" opacity="1.0" quantity="0"/>
18+
<sld:ColorMapEntry color="#fed690" label="5.0 °C" opacity="1.0" quantity="5"/>
19+
<sld:ColorMapEntry color="#fdae61" label="10.0 °C" opacity="1.0" quantity="10"/>
20+
<sld:ColorMapEntry color="#ea633e" label="20.0 °C" opacity="1.0" quantity="20"/>
21+
<sld:ColorMapEntry color="#d7191c" label="&gt;= 30 °C" opacity="1.0" quantity="30"/>
22+
</ColorMap>
23+
</sld:RasterSymbolizer>
24+
</sld:Rule>
25+
</sld:FeatureTypeStyle>
26+
</sld:UserStyle>
27+
</sld:NamedLayer>
28+
</sld:StyledLayerDescriptor>
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<?xml version="1.0" encoding="UTF-8"?><sld:StyledLayerDescriptor xmlns="http://www.opengis.net/sld" xmlns:sld="http://www.opengis.net/sld" xmlns:ogc="http://www.opengis.net/ogc" xmlns:gml="http://www.opengis.net/gml" version="1.0.0">
2+
<sld:NamedLayer>
3+
<sld:Name>uod_precip_total_401</sld:Name>
4+
<sld:UserStyle>
5+
<sld:Name>uod_precip_total_401</sld:Name>
6+
<sld:Title>uod_precip_total_401</sld:Title>
7+
<sld:FeatureTypeStyle>
8+
<sld:Name>name</sld:Name>
9+
<sld:Rule>
10+
<sld:RasterSymbolizer>
11+
<Opacity>1.0</Opacity>
12+
<ColorMap extended="true">
13+
<sld:ColorMapEntry color="#FFFFFF" label="" opacity="0.0" quantity="-1"/>
14+
<sld:ColorMapEntry color="#2b83ba" label="&lt; 5 mm" opacity="1.0" quantity="0"/>
15+
<sld:ColorMapEntry color="#6bb0af" label="20 mm" opacity="1.0" quantity="20"/>
16+
<sld:ColorMapEntry color="#abdda4" label="50 mm" opacity="1.0" quantity="50"/>
17+
<sld:ColorMapEntry color="#d5eeb1" label="100 mm" opacity="1.0" quantity="100"/>
18+
<sld:ColorMapEntry color="#ffffbf" label="150 mm" opacity="1.0" quantity="150"/>
19+
<sld:ColorMapEntry color="#fed690" label="200 mm" opacity="1.0" quantity="200"/>
20+
<sld:ColorMapEntry color="#fdae61" label="250 mm" opacity="1.0" quantity="250"/>
21+
<sld:ColorMapEntry color="#ea633e" label="300 mm" opacity="1.0" quantity="300"/>
22+
<sld:ColorMapEntry color="#d7191c" label="&gt;= 350 mm" opacity="1.0" quantity="350"/>
23+
</ColorMap>
24+
</sld:RasterSymbolizer>
25+
</sld:Rule>
26+
</sld:FeatureTypeStyle>
27+
</sld:UserStyle>
28+
</sld:NamedLayer>
29+
</sld:StyledLayerDescriptor>

dataqs/udatp/resources/uodtest.nc

67.6 KB
Binary file not shown.

dataqs/udatp/resources/uodtest.tif

62 KB
Binary file not shown.

dataqs/udatp/tasks.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
#!/usr/bin/env python
2+
# -*- coding: utf-8 -*-
3+
4+
###############################################################################
5+
# Copyright Kitware Inc. and Epidemico Inc.
6+
#
7+
# Licensed under the Apache License, Version 2.0 ( the "License" );
8+
# you may not use this file except in compliance with the License.
9+
# You may obtain a copy of the License at
10+
#
11+
# http://www.apache.org/licenses/LICENSE-2.0
12+
#
13+
# Unless required by applicable law or agreed to in writing, software
14+
# distributed under the License is distributed on an "AS IS" BASIS,
15+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16+
# See the License for the specific language governing permissions and
17+
# limitations under the License.
18+
###############################################################################
19+
20+
from __future__ import absolute_import
21+
22+
from celery import shared_task
23+
from dataqs.udatp.udatp import UoDAirTempPrecipProcessor
24+
25+
26+
@shared_task
27+
def udatp_task():
28+
processor = UoDAirTempPrecipProcessor()
29+
processor.run()

dataqs/udatp/tests.py

Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
#!/usr/bin/env python
2+
# -*- coding: utf-8 -*-
3+
4+
###############################################################################
5+
# Copyright Kitware Inc. and Epidemico Inc.
6+
#
7+
# Licensed under the Apache License, Version 2.0 ( the "License" );
8+
# you may not use this file except in compliance with the License.
9+
# You may obtain a copy of the License at
10+
#
11+
# http://www.apache.org/licenses/LICENSE-2.0
12+
#
13+
# Unless required by applicable law or agreed to in writing, software
14+
# distributed under the License is distributed on an "AS IS" BASIS,
15+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16+
# See the License for the specific language governing permissions and
17+
# limitations under the License.
18+
###############################################################################
19+
20+
import glob
21+
import os
22+
import unittest
23+
from datetime import date
24+
from django.test import TestCase
25+
from dataqs.udatp.udatp import UoDAirTempPrecipProcessor
26+
from mock import patch
27+
28+
script_dir = os.path.dirname(os.path.realpath(__file__))
29+
30+
31+
def mock_retrbinary_nc(self, name, writer):
32+
"""
33+
Mocks the ftplib.FTP.retrbinary method, writes test image to disk.
34+
"""
35+
with open(os.path.join(script_dir, 'resources/uodtest.nc'), 'rb') as inf:
36+
writer(inf.read())
37+
return None
38+
39+
40+
def mock_retrbinary_tif(self, name, writer):
41+
"""
42+
Mocks the ftplib.FTP.retrbinary method, writes test image to disk.
43+
"""
44+
with open(os.path.join(script_dir, 'resources/uodtest.tif'), 'rb') as inf:
45+
writer(inf.read())
46+
return None
47+
48+
49+
def mock_none(self, *args):
50+
"""
51+
For mocking various FTP methods that should return nothing for tests.
52+
"""
53+
return None
54+
55+
56+
class UoDAirTempPrecipTest(TestCase):
57+
"""
58+
Tests the dataqs.gistemp module. Since each processor is highly
59+
dependent on a running GeoNode instance for most functions, only
60+
independent functions are tested here.
61+
"""
62+
63+
def setUp(self):
64+
self.processor = UoDAirTempPrecipProcessor()
65+
66+
def tearDown(self):
67+
self.processor.cleanup()
68+
69+
@patch('ftplib.FTP', autospec=True)
70+
@patch('ftplib.FTP.retrbinary', mock_retrbinary_nc)
71+
@patch('ftplib.FTP.connect', mock_none)
72+
@patch('ftplib.FTP.login', mock_none)
73+
@patch('ftplib.FTP.cwd', mock_none)
74+
def test_download(self, ftp_mock):
75+
"""
76+
Verify that a file is downloaded
77+
"""
78+
cdf_files = self.processor.download()
79+
for cdf in cdf_files:
80+
self.assertTrue(os.path.exists(cdf))
81+
82+
@patch('ftplib.FTP', autospec=True)
83+
@patch('ftplib.FTP.retrbinary', mock_retrbinary_nc)
84+
@patch('ftplib.FTP.connect', mock_none)
85+
@patch('ftplib.FTP.login', mock_none)
86+
@patch('ftplib.FTP.cwd', mock_none)
87+
def test_cleanup(self, ftp_mock):
88+
self.processor.download()
89+
self.assertNotEqual([], glob.glob(os.path.join(
90+
self.processor.tmp_dir, self.processor.prefix + '*')))
91+
self.processor.cleanup()
92+
self.assertEquals([], glob.glob(os.path.join(
93+
self.processor.tmp_dir, self.processor.prefix + '*')))
94+
95+
def test_date(self):
96+
last_date = self.processor.get_date(1380)
97+
self.assertEquals(last_date, date(2015, 12, 1))
98+
99+
@patch('ftplib.FTP', autospec=True)
100+
@patch('ftplib.FTP.retrbinary', mock_retrbinary_nc)
101+
@patch('ftplib.FTP.connect', mock_none)
102+
@patch('ftplib.FTP.login', mock_none)
103+
@patch('ftplib.FTP.cwd', mock_none)
104+
def test_convert(self, ftp_mock):
105+
cdf_files = self.processor.download()
106+
for cdf in cdf_files:
107+
try:
108+
self.processor.convert(cdf)
109+
self.assertNotEqual([], glob.glob(cdf.replace(
110+
'.nc', '.classic.lng.nc')))
111+
except OSError:
112+
# cdo and/or netcdf not installed
113+
raise unittest.SkipTest()
114+
115+
@patch('ftplib.FTP', autospec=True)
116+
@patch('ftplib.FTP.retrbinary', mock_retrbinary_tif)
117+
@patch('ftplib.FTP.connect', mock_none)
118+
@patch('ftplib.FTP.login', mock_none)
119+
@patch('ftplib.FTP.cwd', mock_none)
120+
def test_extract_band(self, ftp_mock):
121+
cdf = self.processor.download()[0]
122+
tif = cdf.replace('.nc', '.tif')
123+
self.processor.extract_band(cdf, 1, tif)
124+
self.assertTrue(os.path.isfile(tif))

0 commit comments

Comments
 (0)