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

Issue8 sardata #9

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from 2 commits
Commits
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
159 changes: 159 additions & 0 deletions sardata/sardataNBS.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Thu Feb 9 09:32:05 2023

@author: froded
"""

from owslib import fes
from owslib.fes import SortBy, SortProperty
from owslib.csw import CatalogueServiceWeb


class SARData():
"""
A class for getting Sentinel-1 netCDF data from the Norwegian Ground Segment (NBS)

Parameters
-----------
endpoint : str
URL to NBS. Default: https://nbs.csw.met.no/csw

bbox : int list
A boudary box for search area speified in latitude and longitude
bbox = [lon_min, lat_min, lon_max, lat_max]

Example:
>>> bbox = [-10, 75, 40, 85]

start : datetime object
Specify the start time of the range to serchthe

stop : datetime object
Specify the stop time of the range to serchthe

Example:
>>> from datetime import datetime, timedelta
>>> stop = datetime(2010, 1, 1, 12, 30, 59).replace(tzinfo=pytz.utc)
>>> start = stop - timedelta(days=7)

kw_names : str
A search string filter to limit the result of a search.
Example:
>>> kw_name='S1A*'

"""

def __init__(self, endpoint='https://nbs.csw.met.no/csw', bbox=None, start=None, stop=None, kw_names=None, crs="urn:ogc:def:crs:OGC:1.3:CRS84", *args, **kwargs):

constraints = []
csw = None
while csw is None:
try:
# connect
csw = CatalogueServiceWeb(endpoint, timeout=60)
except:
pass

if kw_names:
kw = dict(wildCard="*", escapeChar="\\", singleChar="?", propertyname="apiso:AnyText")
or_filt = fes.Or([fes.PropertyIsLike(literal=("*%s*" % val), **kw) for val in kw_names])
constraints.append(or_filt)



if all(v is not None for v in [start, stop]):
begin, end = self._fes_date_filter(start, stop)
constraints.append(begin)
constraints.append(end)

if bbox:
bbox_crs = fes.BBox(bbox, crs=crs)
constraints.append(bbox_crs)
if len(constraints) >= 2:
filter_list = [
fes.And(
constraints
)
]
else:
filter_list = constraints

self._get_csw_records(csw, filter_list, pagesize=2, maxrecords=10)
self.csw = csw
url_opendap = []

for key, value in list(csw.records.items()):
for ref in value.references:
if ref['scheme'] == 'OPENDAP:OPENDAP':
url_opendap.append(ref['url'])
self.url_opendap = url_opendap




def _get_csw_records(self, csw, filter_list, pagesize=2, maxrecords=10):
"""Iterate `maxrecords`/`pagesize` times until the requested value in
`maxrecords` is reached.
"""
# Iterate over sorted results.
sortby = SortBy([SortProperty("dc:title", "ASC")])
csw_records = {}
startposition = 0
nextrecord = getattr(csw, "results", 1)
while nextrecord != 0:
csw.getrecords2(
constraints=filter_list,
startposition=startposition,
maxrecords=pagesize,
sortby=sortby,
)
csw_records.update(csw.records)
if csw.results["nextrecord"] == 0:
break
startposition += pagesize + 1 # Last one is included.
if startposition >= maxrecords:
break
csw.records.update(csw_records)




def _fes_date_filter(self, start, stop, constraint="within"):
"""
Take datetime-like objects and returns a fes filter for date range
(begin and end inclusive).
NOTE: Truncates the minutes!!!
"""

start = start.strftime("%Y-%m-%d %H:00")
stop = stop.strftime("%Y-%m-%d %H:00")
if constraint == "overlaps":
propertyname = "apiso:TempExtent_begin"
begin = fes.PropertyIsLessThanOrEqualTo(propertyname=propertyname, literal=stop)
propertyname = "apiso:TempExtent_end"
end = fes.PropertyIsGreaterThanOrEqualTo(
propertyname=propertyname, literal=start
)
elif constraint == "within":
propertyname = "apiso:TempExtent_begin"
begin = fes.PropertyIsGreaterThanOrEqualTo(
propertyname=propertyname, literal=start
)
propertyname = "apiso:TempExtent_end"
end = fes.PropertyIsLessThanOrEqualTo(propertyname=propertyname, literal=stop)
else:
raise NameError("Unrecognized constraint {}".format(constraint))
return begin, end











15 changes: 15 additions & 0 deletions tests/test_sarwind.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@

from sarwind.sarwind import SARWind

from sardata.sardataNBS import SARData
from datetime import datetime, timedelta
import pytz

@pytest.mark.unittests
@pytest.mark.sarwind
Expand Down Expand Up @@ -79,3 +82,15 @@ def testSARWind_using_s1IWDVsafe_meps_filenames(sarIW_SAFE, meps):
"""
w = SARWind(sarIW_SAFE, meps)
assert type(w) == SARWind

@pytest.mark.sardata
def testSARData_from_NBS():
""" Test using CSW for reading Sentinel-1 data.
This test requres access to https://nbs.csw.met.no/csw
"""
bbox = [-10, 75, 40, 85]
stop = datetime(2022, 1, 8, 5, 30, 59).replace(tzinfo=pytz.utc)
start = stop - timedelta(days=1)

sw = SARData(bbox=bbox, start=start, stop=stop, kw_name='S1A*')
assert type(sw) == SARData