From 38492e477f25c3e8b7eaee911bc238bfa5ebf83d Mon Sep 17 00:00:00 2001 From: BuddyVolly Date: Fri, 17 Sep 2021 15:50:34 +0200 Subject: [PATCH 01/13] preparing for pypi package --- .gitignore | 3 +- README.md | 89 +++++++++++++----------------------------------------- setup.py | 16 +++++++--- 3 files changed, 35 insertions(+), 73 deletions(-) diff --git a/.gitignore b/.gitignore index 9508de76..a8f3b911 100755 --- a/.gitignore +++ b/.gitignore @@ -6,4 +6,5 @@ __pycache__ htmlcov .empty .DS_Store -ost/.DS_Store \ No newline at end of file +ost/.DS_Store +build \ No newline at end of file diff --git a/README.md b/README.md index 5a84a190..9fa01ee8 100755 --- a/README.md +++ b/README.md @@ -32,19 +32,23 @@ https://github.com/ESA-PhiLab/OST_Notebooks for getting started. ### Docker -A docker image is available from docker hub that contains the full package, +**Update!** + +Dockerhub is not permitting automatic builds. Therefore you need to +build your own docker image using the DOCKERFIlE https://raw.githubusercontent.com/ESA-PhiLab/OpenSarToolkit/main/Dockerfile + +The resulting docker image contains the full package, including ESA's Sentinel-1 Toolbox, Orfeo Toolbox, Jupyter Lab as well -as the Open SAR Toolkit the tutorial notebooks. +as the Open SAR Toolkit tutorial notebooks. Docker installation is possible on various OS. Installation instructions can be found at https://docs.docker.com/install/ After docker is installed and running, launch the container with -(adapt the path to the shared host folder): +(adapt the path to the shared host folder and the name of the docke rimage at the very end): ``` -docker pull buddyvolly/opensartoolkit -docker run -it -p 8888:8888 -v /shared/folder/on/host:/home/ost/shared buddyvolly/opensartoolkit +docker run -it -p 8888:8888 -v /shared/folder/on/host:/home/ost/shared docker/image ``` The docker image automatically executes the jupyter lab and runs it on @@ -68,6 +72,8 @@ If you install SNAP into the standard directory, OST should have no problems to find the SNAP command line executable. Otherwise you need to define the path to the gpt file on your own during processing. +**Make sure to use SNAP 8 with the latest updates installed.** + ##### Orfeo Toolbox If you want to create mosaics between different swaths, OST will rely on the @@ -78,79 +84,25 @@ https://www.orfeo-toolbox.org/download/ Make sure that the Orfeo bin folder is within your PATH variable to allow execution from command line. -#### OST installation - -OST is developed under Ubuntu 18.04 OS in python 3.6. It has not been tested -much on other OS and python versions, but should in principle work on any OS -and any python version >= 3.5. - -##### Ubuntu/Debian Linux (using pip) - -Before installation of OST, run the following line on the terminal to -install further dependencies: - -``` -sudo apt install python3-pip git libgdal-dev python3-gdal libspatialindex-dev nodejs npm -``` - -then install OST as a global package (for all users, admin rights needed): +##### Further dependencies (libs etc) +Ubuntu 18.04 and later: ``` -sudo pip3 install git+https://github.com/ESA-PhiLab/OpenSarToolkit.git +sudo apt install python3-pip git libgdal-dev python3-gdal libspatialindex-dev nodejs npm libgfortran5 ``` -or as local package within your home folder (no admin rights needed): - -``` -pip3 install --user git+https://github.com/ESA-PhiLab/OpenSarToolkit.git -``` +Any Operating system using (mini)conda https://www.anaconda.com/: -run those commands to enable the correct display of progress bars ``` -sudo pip3 install jupyterlab -# this is needed for the progress bar when downloading -sudo jupyter-labextension install @jupyter-widgets/jupyterlab-manager -sudo jupyter nbextension enable --py widgetsnbextension -``` - -##### Mac OS (using homebrew/pip) - -If not already installed, install homebrew as explained on https://brew.sh - -After installation of homebrew, open the terminal and install -further dependecies: - -``` -brew install python3 gdal2 gdal2-python git -``` - -then install OST with python pip: -``` -pip3 install git+https://github.com/ESA-PhiLab/OpenSarToolkit.git - -# this is needed for the progress bar when downloading data -jupyter labextension install @jupyter-widgets/jupyterlab-manager -jupyter nbextension enable --py widgetsnbextension +conda install pip gdal jupyter jupyterlab git matplotlib numpy rasterio imageio rtree geopandas fiona shapely matplotlib descartes tqdm scipy joblib retrying pytest pytest-cov nodejs ``` -##### Conda Installation (Windows, Mac, Linux) - -Follow the installation instructions for conda (Miniconda is sufficient) at: -https://docs.conda.io/projects/conda/en/latest/user-guide/install/ - -Then run the conda command to install OST's dependencies: -``` -conda install pip gdal jupyter jupyterlab git matplotlib numpy rasterio imageio rtree geopandas fiona shapely matplotlib descartes tqdm scipy joblib retrying pytest pytest-cov nodejs +#### OST installation -# this is needed for the progress bar when downloading -jupyter labextension install @jupyter-widgets/jupyterlab-manager -jupyter nbextension enable --py widgetsnbextension -``` +You can use then use pip to install Open SAR Toolkit: -Finally get the OST by using pip -(we will work in future on a dedicated conda package for OST). ``` -pip install git+https://github.com/ESA-PhiLab/OpenSarToolkit.git +pip install opensartoolkit ``` @@ -206,5 +158,6 @@ that are developed in parallel to this core package and should help to get start ## Author -* Andreas Vollrath, ESA +* Andreas Vollrath, FAO (ex-ESA philab) * Petr Sevcik, EOX +* James Wheeler, ESA philab diff --git a/setup.py b/setup.py index 26cc98ae..5d299a00 100755 --- a/setup.py +++ b/setup.py @@ -1,6 +1,12 @@ import os +import pathlib from setuptools import setup, find_packages +# The directory containing this file +HERE = pathlib.Path(__file__).parent + +# The text of the README file +README = (HERE / "README.md").read_text() def parse_requirements(file): return sorted(set( @@ -12,20 +18,22 @@ def parse_requirements(file): setup( - name='ost', + name='opensartoolkit', packages=find_packages(), include_package_data=True, - version='0.11.1', + version='0.12.1', description='High-level functionality for the inventory, download ' 'and pre-processing of Sentinel-1 data', install_requires=parse_requirements('requirements.txt'), url='https://github.com/ESA-PhiLab/OpenSarToolkit', - author='Andreas Vollrath, Petr Sevcik', - author_email='andreas.vollrath[at]esa.int, petr.sevcik[at]eox.at', + author='Andreas Vollrath', + author_email="opensarkit@gmail.com", license='MIT License', keywords=['Sentinel-1', 'ESA', 'SAR', 'Radar', 'Earth Observation', 'Remote Sensing', 'Synthetic Aperture Radar'], + long_description=README, + long_description_content_type="text/markdown", zip_safe=False, setup_requires=['pytest-runner'], tests_require=['pytest'] From 10c6c23ce6dee116207028c02a0ecd6f4591ee28 Mon Sep 17 00:00:00 2001 From: BuddyVolly Date: Fri, 17 Sep 2021 15:50:49 +0200 Subject: [PATCH 02/13] preparing for pypi package --- .gitignore | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index a8f3b911..4939d29b 100755 --- a/.gitignore +++ b/.gitignore @@ -7,4 +7,5 @@ htmlcov .empty .DS_Store ost/.DS_Store -build \ No newline at end of file +build +dist \ No newline at end of file From 071d9848af2b30197f8dc6a7f40bb9945610cc92 Mon Sep 17 00:00:00 2001 From: BuddyVolly Date: Fri, 17 Sep 2021 17:35:31 +0200 Subject: [PATCH 03/13] removing literals and adapt setup.py for pypi package --- ost/helpers/db.py | 2 +- ost/s1/burst_batch.py | 2 +- setup.py | 33 +++++++++++++++++++++------------ 3 files changed, 23 insertions(+), 14 deletions(-) diff --git a/ost/helpers/db.py b/ost/helpers/db.py index e8e383b3..70c92201 100644 --- a/ost/helpers/db.py +++ b/ost/helpers/db.py @@ -151,7 +151,7 @@ def shpGeom2pg(self, aoi, tablename): feature = layer.GetFeature(i) wkt = feature.GetGeometryRef().ExportToWkt() - if inProj4 is not '+proj=longlat +datum=WGS84 +no_defs': + if inProj4 != '+proj=longlat +datum=WGS84 +no_defs': wkt = reproject_geometry(wkt, inProj4, 4326) wkt = 'St_GeomFromText(\'{}\', 4326)'.format(wkt) diff --git a/ost/s1/burst_batch.py b/ost/s1/burst_batch.py index da7ef3dc..de9e1dbf 100644 --- a/ost/s1/burst_batch.py +++ b/ost/s1/burst_batch.py @@ -309,7 +309,7 @@ def _create_timeseries(burst_gdf, config_file): product, product_name = list(pr) # take care of H-A-Alpha naming for file search - if pol in ['Alpha', 'Entropy', 'Anisotropy'] and product is 'pol': + if pol in ['Alpha', 'Entropy', 'Anisotropy'] and product == 'pol': list_of_files = sorted( list(burst_dir.glob(f'20*/*data*/*{pol}*img'))) else: diff --git a/setup.py b/setup.py index 5d299a00..4939e661 100755 --- a/setup.py +++ b/setup.py @@ -1,4 +1,3 @@ -import os import pathlib from setuptools import setup, find_packages @@ -8,23 +7,33 @@ # The text of the README file README = (HERE / "README.md").read_text() -def parse_requirements(file): - return sorted(set( - line.partition('#')[0].strip() - for line in open(os.path.join(os.path.dirname(__file__), file)) - ) - -set('') - ) - - setup( name='opensartoolkit', packages=find_packages(), include_package_data=True, - version='0.12.1', + version='0.12.2', description='High-level functionality for the inventory, download ' 'and pre-processing of Sentinel-1 data', - install_requires=parse_requirements('requirements.txt'), + install_requires=[ + 'descartes', + 'fiona', + 'gdal>=2', + 'godale', + 'geopandas>=0.8', + 'jupyterlab', + 'matplotlib', + 'numpy', + 'pandas', + 'psycopg2-binary', + 'rasterio', + 'requests', + 'scipy', + 'shapely', + 'tqdm', + 'imageio', + 'rtree', + 'retrying' + ], url='https://github.com/ESA-PhiLab/OpenSarToolkit', author='Andreas Vollrath', author_email="opensarkit@gmail.com", From dc63de585404c8d5cc7ac580551984e40bd2ad55 Mon Sep 17 00:00:00 2001 From: BuddyVolly Date: Mon, 20 Sep 2021 10:53:28 +0200 Subject: [PATCH 04/13] resolve EPSG:4326 issue --- ost/generic/common_wrappers.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ost/generic/common_wrappers.py b/ost/generic/common_wrappers.py index a93e1ce6..76e2b9dd 100644 --- a/ost/generic/common_wrappers.py +++ b/ost/generic/common_wrappers.py @@ -192,7 +192,7 @@ def terrain_correction(infile, outfile, logfile, config_dict): projection = f"AUTO:{dem_dict['out_projection']}" # epsg codes elif int(dem_dict['out_projection']) == 4326: - projection = CRS.from_epsg(4326).to_wkt() + projection = 'WGS84(DD)' else: projection = f"EPSG:{dem_dict['out_projection']}" @@ -277,7 +277,7 @@ def ls_mask(infile, outfile, logfile, config_dict): projection = f"AUTO:{dem_dict['out_projection']}" # epsg codes elif int(dem_dict['out_projection']) == 4326: - projection = CRS.from_epsg(4326).to_wkt() + projection = 'WGS84(DD)' else: projection = f"EPSG:{dem_dict['out_projection']}" From 8d4a03634bda1da0bc285c9245a2a47e0648bda1 Mon Sep 17 00:00:00 2001 From: BuddyVolly Date: Mon, 20 Sep 2021 10:55:49 +0200 Subject: [PATCH 05/13] rename var file ot generic format --- Dockerfile | 10 +++++----- setup.py | 2 +- snap8.varfile => snap.varfile | 0 3 files changed, 6 insertions(+), 6 deletions(-) rename snap8.varfile => snap.varfile (100%) diff --git a/Dockerfile b/Dockerfile index 189e5d5b..f3e477ef 100755 --- a/Dockerfile +++ b/Dockerfile @@ -1,13 +1,13 @@ FROM ubuntu:18.04 -LABEL maintainer="Petr Sevcik, EOX" -LABEL OpenSARToolkit='0.11.1' +LABEL maintainer="Andreas Vollrath, FAO" +LABEL OpenSARToolkit='0.12.3' # set work directory to home and download snap WORKDIR /home/ost # copy the snap installation config file into the container -COPY snap8.varfile $HOME +COPY snap.varfile $HOME # update variables ENV OTB_VERSION="7.3.0" \ @@ -42,9 +42,9 @@ RUN alias python=python3 && \ mkdir /home/ost/programs && \ wget $SNAP_URL/$TBX && \ chmod +x $TBX && \ - ./$TBX -q -varfile snap7.varfile && \ + ./$TBX -q -varfile snap.varfile && \ rm $TBX && \ - rm snap7.varfile && \ + rm snap.varfile && \ cd /home/ost/programs && \ wget https://www.orfeo-toolbox.org/packages/${OTB} && \ chmod +x $OTB && \ diff --git a/setup.py b/setup.py index 4939e661..2e330e58 100755 --- a/setup.py +++ b/setup.py @@ -11,7 +11,7 @@ name='opensartoolkit', packages=find_packages(), include_package_data=True, - version='0.12.2', + version='0.12.3', description='High-level functionality for the inventory, download ' 'and pre-processing of Sentinel-1 data', install_requires=[ diff --git a/snap8.varfile b/snap.varfile similarity index 100% rename from snap8.varfile rename to snap.varfile From 2d9d5fb2c5b5cbc1fd17e01a4bc2cdd05a1409c1 Mon Sep 17 00:00:00 2001 From: BuddyVolly Date: Mon, 20 Sep 2021 15:29:44 +0200 Subject: [PATCH 06/13] new file for connection check with scihub --- Dockerfile | 2 +- ost/helpers/scihub.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Dockerfile b/Dockerfile index f3e477ef..16004cb1 100755 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM ubuntu:18.04 +FROM ubuntu:20.04 LABEL maintainer="Andreas Vollrath, FAO" LABEL OpenSARToolkit='0.12.3' diff --git a/ost/helpers/scihub.py b/ost/helpers/scihub.py index fb697e9f..c4fa1e81 100644 --- a/ost/helpers/scihub.py +++ b/ost/helpers/scihub.py @@ -198,8 +198,8 @@ def check_connection(uname, pword, # we use some random url for checking (also for czech mirror) url = ( - f'{base_url}/odata/v1/Products?' - '$select=Id&$filter=substringof(%27_20200714T165921_%27,Name)' + f'{base_url}/odata/v1/Products(' + '\'8f30a536-c01c-4ef4-ac74-be3378dc44c4\')/$value' ) response = requests.get(url, auth=(uname, pword), stream=True) From d34b59e51b812e3ca03c775e59a00e68ec528c3a Mon Sep 17 00:00:00 2001 From: BuddyVolly Date: Mon, 20 Sep 2021 17:54:00 +0200 Subject: [PATCH 07/13] fixing geodesic buffer for new proj lib --- ost/Project.py | 2 +- ost/helpers/vector.py | 27 ++++++++++++++------------- 2 files changed, 15 insertions(+), 14 deletions(-) diff --git a/ost/Project.py b/ost/Project.py index e0a0c705..f4f84a7e 100644 --- a/ost/Project.py +++ b/ost/Project.py @@ -366,7 +366,7 @@ def download(self, inventory_df, mirror=None, concurrent=2, download_df = inventory_df[inventory_df.download_path == 'None'] # to download or not ot download - that is here the question - if not download_df.any().any(): + if download_df.empty: logger.info('All scenes are ready for being processed.') else: logger.info('One or more scene(s) need(s) to be downloaded.') diff --git a/ost/helpers/vector.py b/ost/helpers/vector.py index 89dd33e7..590ff2be 100644 --- a/ost/helpers/vector.py +++ b/ost/helpers/vector.py @@ -171,7 +171,7 @@ def reproject_geometry(geom, inproj4, out_epsg): return geom -def geodesic_point_buffer(lat, lon, meters, envelope=False): +def geodesic_point_buffer(lon, lat, meters, envelope=False): """ :param lat: @@ -181,23 +181,24 @@ def geodesic_point_buffer(lat, lon, meters, envelope=False): :return: """ - # get WGS 84 proj - proj_wgs84 = pyproj.Proj('epsg:4326') - - # Azimuthal equidistant projection - aeqd_proj = '+proj=aeqd +lat_0={lat} +lon_0={lon} +x_0=0 +y_0=0' - project = partial( - pyproj.transform, - pyproj.Proj(aeqd_proj.format(lat=lat, lon=lon)), - proj_wgs84 + proj_crs = ProjectedCRS( + conversion=AzumuthalEquidistantConversion(float(lat), float(lon)) ) + proj_wgs84 = pyproj.Proj('EPSG:4326') + + Trans = pyproj.Transformer.from_proj( + proj_crs, + proj_wgs84, + always_xy=True + ).transform + buf = Point(0, 0).buffer(meters) # distance in metres if envelope is True: - geom = Polygon(transform(project, buf).exterior.coords[:]).envelope + geom = Polygon(transform(Trans, buf).exterior.coords[:]).envelope else: - geom = Polygon(transform(project, buf).exterior.coords[:]) + geom = Polygon(transform(Trans, buf).exterior.coords[:]) return geom.wkt @@ -240,7 +241,7 @@ def latlon_to_wkt( aoi_wkt = aoi_geom.to_wkt() elif buffer_meter: - aoi_wkt = geodesic_point_buffer(lat, lon, buffer_meter, envelope) + aoi_wkt = geodesic_point_buffer(lon, lat, buffer_meter, envelope) return aoi_wkt From 3a9bf81240332912a14b5d095aaf66d3bcb12d88 Mon Sep 17 00:00:00 2001 From: BuddyVolly Date: Tue, 21 Sep 2021 11:11:50 +0200 Subject: [PATCH 08/13] add pyproj requirement version 2.1 --- setup.py | 1 + 1 file changed, 1 insertion(+) diff --git a/setup.py b/setup.py index 2e330e58..1a8aae54 100755 --- a/setup.py +++ b/setup.py @@ -20,6 +20,7 @@ 'gdal>=2', 'godale', 'geopandas>=0.8', + 'pyproj>=2.1', 'jupyterlab', 'matplotlib', 'numpy', From 7a1e9ecd3590c2ca724c012821223b0723fef7eb Mon Sep 17 00:00:00 2001 From: BuddyVolly Date: Tue, 21 Sep 2021 11:12:08 +0200 Subject: [PATCH 09/13] add pyproj requirement version 2.1 --- requirements.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/requirements.txt b/requirements.txt index f1868e88..50362e8c 100755 --- a/requirements.txt +++ b/requirements.txt @@ -2,6 +2,7 @@ descartes fiona gdal>=2 godale +pyproj>=2.1 geopandas>=0.8 jupyterlab matplotlib From 51c938c81d1e2bd532593616708156531707981d Mon Sep 17 00:00:00 2001 From: BuddyVolly Date: Tue, 21 Sep 2021 11:39:24 +0200 Subject: [PATCH 10/13] fix pyprj imports --- ost/helpers/vector.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ost/helpers/vector.py b/ost/helpers/vector.py index 590ff2be..633024f6 100644 --- a/ost/helpers/vector.py +++ b/ost/helpers/vector.py @@ -1,9 +1,10 @@ import os import json -from functools import partial from pathlib import Path import pyproj +from pyproj.crs import ProjectedCRS +from pyproj.crs.coordinate_operation import AzumuthalEquidistantConversion import geopandas as gpd import logging From 5c6896bd80999fde0537c2bcc4147bd0b9fc51d4 Mon Sep 17 00:00:00 2001 From: BuddyVolly Date: Tue, 21 Sep 2021 15:23:57 +0200 Subject: [PATCH 11/13] fix harmonics model_mean mosaic --- ost/s1/burst_batch.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ost/s1/burst_batch.py b/ost/s1/burst_batch.py index de9e1dbf..9d51b984 100644 --- a/ost/s1/burst_batch.py +++ b/ost/s1/burst_batch.py @@ -654,7 +654,7 @@ def mosaic_timescan(burst_inventory, config_file): if 'harmonics' in metrics: metrics.remove('harmonics') - metrics.extend(['amplitude', 'phase', 'residuals']) + metrics.extend(['amplitude', 'phase', 'residuals', 'model_mean']) if 'percentiles' in metrics: metrics.remove('percentiles') From c289e5ca092bf835eeb46af329f4e782a5c67f7f Mon Sep 17 00:00:00 2001 From: BuddyVolly Date: Tue, 21 Sep 2021 15:31:18 +0200 Subject: [PATCH 12/13] fix SRTM download --- ost/Project.py | 8 ++++---- ost/helpers/srtm.py | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/ost/Project.py b/ost/Project.py index f4f84a7e..524d39b0 100644 --- a/ost/Project.py +++ b/ost/Project.py @@ -3,6 +3,7 @@ # ------ bug of rasterio -------- import os + if "GDAL_DATA" in list(os.environ.keys()): del os.environ["GDAL_DATA"] if "PROJ_LIB" in list(os.environ.keys()): @@ -69,7 +70,7 @@ def __init__( logger.info('Project directory already exists. ' 'No data has been deleted at this point but ' 'make sure you really want to use this folder.') - + # define project sub-directories if not set, and create folders self.download_dir = self.project_dir.joinpath('download') self.download_dir.mkdir(parents=True, exist_ok=True) @@ -617,7 +618,6 @@ def pre_download_srtm(self): logger.info('Pre-downloading SRTM tiles') srtm.download_srtm(self.aoi) - def bursts_to_ards( self, timeseries=False, @@ -712,13 +712,13 @@ def bursts_to_ards( if overwrite: logger.info('Deleting processing folder to start from scratch') h.remove_folder_content(self.config_dict['processing_dir']) - + # -------------------------------------------- # 5 set resolution to degree # self.ard_parameters['resolution'] = h.resolution_in_degree( # self.center_lat, self.ard_parameters['resolution']) - if self.config_dict['max_workers'] > 1: + if self.config_dict['max_workers'] > 1 and self.ard_parameters['single_ARD']['dem']['dem_name'] == 'SRTM 1Sec HGT': self.pre_download_srtm() # -------------------------------------------- diff --git a/ost/helpers/srtm.py b/ost/helpers/srtm.py index d32f1f5c..684b6b78 100644 --- a/ost/helpers/srtm.py +++ b/ost/helpers/srtm.py @@ -95,13 +95,13 @@ def download_srtm(aoi): warnings.filterwarnings( 'ignore', 'Geometry is in a geographic CRS', UserWarning ) - srtm = gpd.read_file( - OST_ROOT.joinpath('aux/srtm1sectiles.gpkg') - ) + + srtm = gpd.read_file(OST_ROOT.joinpath('aux/srtm1sectiles.gpkg')) aoi_gdf = vec.wkt_to_gdf(aoi) aoi_gdf['geometry'] = aoi_gdf.geometry.buffer(1) overlap_df = gpd.overlay(srtm, aoi_gdf, how='intersection') + iter_list = [] for file in overlap_df.url.values: iter_list.append(file) From c7e57b9737076252cdaf62cf5cfd6e9451faefab Mon Sep 17 00:00:00 2001 From: BuddyVolly Date: Tue, 21 Sep 2021 15:48:24 +0200 Subject: [PATCH 13/13] + 1 debug version --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 1a8aae54..1e48c0da 100755 --- a/setup.py +++ b/setup.py @@ -11,7 +11,7 @@ name='opensartoolkit', packages=find_packages(), include_package_data=True, - version='0.12.3', + version='0.12.4', description='High-level functionality for the inventory, download ' 'and pre-processing of Sentinel-1 data', install_requires=[