Skip to content

Commit a78ead1

Browse files
authored
Merge pull request #97 from bird-house/ncml
Process creating NcML file aggregating netCDF files
2 parents dea910c + 1f948a0 commit a78ead1

9 files changed

Lines changed: 186 additions & 5 deletions

File tree

emu/processes/__init__.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,10 @@
1616
from .wps_ncmeta import NCMeta
1717
from .wps_nonpyid import NonPyID
1818
from .wps_dry_run import SimpleDryRun
19+
from .wps_ncml import NcMLAgg
1920
from .wps_translation import Translation
2021

22+
2123
processes = [
2224
UltimateQuestion(),
2325
Sleep(),
@@ -37,5 +39,6 @@
3739
NCMeta(),
3840
NonPyID(),
3941
SimpleDryRun(),
42+
NcMLAgg(),
4043
Translation(),
4144
]

emu/processes/wps_nc_to_dap.py

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
from pywps import Process
2+
from pywps import ComplexInput, ComplexOutput, FORMATS
3+
from pywps.app.Common import Metadata
4+
from pywps import configuration
5+
import logging
6+
7+
8+
LOGGER = logging.getLogger("PYWPS")
9+
10+
# This needs some more thoughts before going live to decide how the WPS server should be configured to communicate
11+
# with the DAP server.
12+
13+
14+
class NcToDap(Process):
15+
def __init__(self):
16+
inputs = [
17+
ComplexInput('resource', "NetCDF file",
18+
abstract="Link to NetCDF or NcML file on this server",
19+
supported_formats=[FORMATS.NETCDF, ], # FORMATS.NCML], to become available in PyWPS 4.2.5
20+
min_occurs=1,
21+
max_occurs=1)
22+
]
23+
outputs = [
24+
ComplexOutput('dap', 'DAP url',
25+
as_reference=True,
26+
supported_formats=[FORMATS.DODS]),
27+
]
28+
29+
super(NcToDap, self).__init__(
30+
self._handler,
31+
identifier='nc_to_dap',
32+
title="Convert file URL to DAP URL",
33+
abstract="Return Data Access Protocol link to a netCDF or NcML file.",
34+
version="1",
35+
metadata=[
36+
Metadata('User Guide', 'http://emu.readthedocs.io/en/latest/'),
37+
],
38+
inputs=inputs,
39+
outputs=outputs,
40+
store_supported=True,
41+
status_supported=True)
42+
43+
@staticmethod
44+
def _handler(self, request, response):
45+
url = request.inputs['resource'][0].url
46+
47+
# Write response
48+
file_server = configuration.CONFIG.get("server", "outputurl")
49+
dap_server = configuration.CONFIG.get("dap", "outputurl")
50+
51+
response.outputs["dap"].url = url.replace(file_server, dap_server)
52+
53+
return response

emu/processes/wps_ncml.py

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
import os
2+
import xarray.tests.test_dataset as td
3+
from pywps import Process
4+
from pywps import ComplexOutput, FORMATS
5+
from pywps.app.Common import Metadata
6+
import logging
7+
8+
9+
LOGGER = logging.getLogger("PYWPS")
10+
11+
12+
class NcMLAgg(Process):
13+
def __init__(self):
14+
inputs = []
15+
outputs = [
16+
ComplexOutput('d1', 'NetCDF file 1',
17+
as_reference=True,
18+
supported_formats=[FORMATS.NETCDF]),
19+
ComplexOutput('d2', 'NetCDF file 2',
20+
as_reference=True,
21+
supported_formats=[FORMATS.NETCDF]),
22+
ComplexOutput('ncml', 'NcML aggregation',
23+
as_reference=True,
24+
supported_formats=[FORMATS.DODS]), # FORMATS.NCML To become available in PyWPS 4.2.5
25+
]
26+
27+
super(NcMLAgg, self).__init__(
28+
self._handler,
29+
identifier='ncml',
30+
title="Test NcML THREDDS capability",
31+
abstract="Return links to an NcML file aggregating netCDF files with moving time units.",
32+
version="1",
33+
metadata=[
34+
Metadata('User Guide', 'http://emu.readthedocs.io/en/latest/'),
35+
],
36+
inputs=inputs,
37+
outputs=outputs,
38+
store_supported=True,
39+
status_supported=True)
40+
41+
def _handler(self, request, response):
42+
43+
# Create test datasets
44+
d1, d2, _ = td.create_append_test_data()
45+
46+
# Save datasets to disk
47+
d1fn = os.path.join(self.workdir, "d1.nc")
48+
d2fn = os.path.join(self.workdir, "d2.nc")
49+
50+
d1.to_netcdf(d1fn)
51+
d2.to_netcdf(d2fn)
52+
53+
# Create NcML aggregation
54+
ncml = """
55+
<netcdf xmlns="http://www.unidata.ucar.edu/namespaces/netcdf/ncml-2.2">
56+
<aggregation dimName="time" type="joinExisting">
57+
<scan location="." suffix=".nc" subdirs="false"/>
58+
</aggregation>
59+
</netcdf>
60+
"""
61+
62+
# Write response
63+
response.outputs["d1"].file = d1fn
64+
response.outputs["d2"].file = d2fn
65+
66+
response.outputs['ncml'].data = ncml
67+
68+
return response

requirements.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,4 @@ click
44
psutil
55
defusedxml
66
geomet
7+
netCDF4

setup.cfg

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,18 +19,20 @@ search = Version="{current_version}"
1919
replace = Version="{new_version}"
2020

2121
[tool:pytest]
22-
addopts =
22+
addopts =
2323
--strict
2424
--tb=native
2525
python_files = test_*.py
26-
markers =
26+
markers =
2727
online: mark test to need internet connection
2828
slow: mark test to be slow
29+
flaky: mark test to be flaky
30+
network: mark test to need network
2931

3032
[flake8]
3133
ignore = F401,E402
3234
max-line-length = 120
33-
exclude =
35+
exclude =
3436
.git,
3537
__pycache__,
3638
docs/source/conf.py,

tests/test_wps_caps.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ def test_wps_caps():
2323
'multiple_outputs',
2424
'nap',
2525
'ncmeta',
26+
'ncml',
2627
'non.py-id',
2728
'output_formats',
2829
'poly_centroid',

tests/test_wps_nc_to_dap.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import pytest
2+
3+
from pywps import Service
4+
from pywps.tests import assert_response_success
5+
6+
from .common import client_for, get_output
7+
from emu.processes.wps_nc_to_dap import NcToDap
8+
from emu.processes.wps_output_formats import OutputFormats
9+
10+
11+
@pytest.mark.skip
12+
def test_wps_nc_to_dap():
13+
# Create netCDF file on server
14+
client = client_for(Service(processes=[OutputFormats()]))
15+
resp = client.get(
16+
service='WPS', request='Execute', version='1.0.0',
17+
identifier='output_formats',)
18+
nc_url = get_output(resp.xml)['netcdf']
19+
20+
# Convert to DAP link
21+
client = client_for(Service(processes=[NcToDap()]))
22+
datainputs = "resource=@xlink:href={0}".format(nc_url)
23+
resp = client.get(
24+
service='wps', request='execute', version='1.0.0',
25+
identifier='nc_to_dap',
26+
datainputs=datainputs)
27+
assert_response_success(resp)
28+
assert 'dodsC' in get_output(resp.xml)['dap']

tests/test_wps_ncml.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import pytest
2+
3+
from pywps import Service
4+
from pywps.tests import assert_response_success
5+
from emu.processes.wps_ncml import NcMLAgg
6+
from .common import client_for, CFG_FILE
7+
from owslib.wps import WPSExecution
8+
9+
10+
@pytest.mark.online
11+
def test_wps_ncml():
12+
13+
client = client_for(Service(processes=[NcMLAgg()], cfgfiles=CFG_FILE))
14+
15+
resp = client.get(
16+
service='wps', request='execute', version='1.0.0',
17+
identifier='ncml')
18+
19+
assert_response_success(resp)
20+
21+
ex = WPSExecution()
22+
ex.parseResponse(resp.xml)
23+
d1, d2, d3 = ex.processOutputs
24+
ncml = d3.retrieveData()
25+
assert ncml.strip().startswith("<")

tests/test_wps_output_formats.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
from pywps import Service
22
from pywps.tests import assert_response_success
33

4-
from .common import client_for
4+
from .common import client_for, CFG_FILE
55
from emu.processes.wps_output_formats import OutputFormats
66

77

88
def test_wps_output_formats():
9-
client = client_for(Service(processes=[OutputFormats()]))
9+
client = client_for(Service(processes=[OutputFormats()], cfgfiles=CFG_FILE))
1010
resp = client.get(
1111
service='WPS', request='Execute', version='1.0.0',
1212
identifier='output_formats',)

0 commit comments

Comments
 (0)