-
Notifications
You must be signed in to change notification settings - Fork 29
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #33 from pflickin/feature/corine
Add method for creating CORINE Land Cover.
- Loading branch information
Showing
19 changed files
with
393 additions
and
0 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
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 @@ | ||
../stactools_corine/stactools/corine/ |
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,59 @@ | ||
from collections import abc | ||
from copy import deepcopy | ||
|
||
import pyproj | ||
|
||
|
||
def epsg_from_utm_zone_number(utm_zone_number, south): | ||
"""Return the EPSG code for a UTM zone number. | ||
Args: | ||
utm_zone_number (int): The UTM zone number. | ||
south (bool): Whether this UTM zone is a south zone. | ||
Returns: | ||
int: The EPSG code number for the UTM zone. | ||
""" | ||
crs = pyproj.CRS.from_dict({ | ||
'proj': 'utm', | ||
'zone': utm_zone_number, | ||
'south': south | ||
}) | ||
|
||
return int(crs.to_authority()[1]) | ||
|
||
|
||
def reproject_geom(src_crs, dest_crs, geom): | ||
"""Reprojects a geometry represented as GeoJSON | ||
from the src_crs to the dest crs. | ||
Args: | ||
src_crs (str): String that can be passed into | ||
pyproj.Transformer.from_crs, e.g. "epsg:4326" | ||
representing the current CRS of the geometry. | ||
dest_crs (str): Similar to src_crs, representing the | ||
desired CRS of the returned geometry. | ||
geom (dict): The GeoJSON geometry | ||
Returns: | ||
dict: The reprojected geometry | ||
""" | ||
transformer = pyproj.Transformer.from_crs(src_crs, | ||
dest_crs, | ||
always_xy=True) | ||
result = deepcopy(geom) | ||
|
||
def fn(coords): | ||
coords = list(coords) | ||
for i in range(0, len(coords)): | ||
coord = coords[i] | ||
if isinstance(coord[0], abc.Sequence): | ||
coords[i] = fn(coord) | ||
else: | ||
x, y = coord | ||
coords[i] = transformer.transform(x, y) | ||
return coords | ||
|
||
result['coordinates'] = fn(result['coordinates']) | ||
|
||
return result |
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,3 @@ | ||
# stactools_corine | ||
|
||
A subpackage of stactools for working with CORINE data. |
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,2 @@ | ||
rasterio==1.1.8 --no-binary=rasterio | ||
pyproj==3.0.0.post1 |
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,49 @@ | ||
import os | ||
from imp import load_source | ||
from setuptools import setup, find_namespace_packages | ||
from glob import glob | ||
import io | ||
|
||
name = 'stactools_corine' | ||
description = ( | ||
"Subpackage for working with CORINE Land Cover data in stactools, " | ||
"a command line tool and Python library for working with STAC.") | ||
|
||
__version__ = load_source( | ||
'stactools.corine.version', | ||
os.path.join(os.path.dirname(__file__), | ||
'stactools/corine/version.py')).__version__ | ||
|
||
from os.path import (basename, splitext) | ||
|
||
here = os.path.abspath(os.path.dirname(__file__)) | ||
|
||
# get the dependencies and installs | ||
with io.open(os.path.join(here, 'requirements.txt'), encoding='utf-8') as f: | ||
install_requires = [line.split(' ')[0] for line in f.read().split('\n')] | ||
|
||
# Add stactools subpackage dependencies | ||
install_requires.extend(['stactools_core=={}'.format(__version__)]) | ||
|
||
with open(os.path.join(here, 'README.md')) as readme_file: | ||
readme = readme_file.read() | ||
|
||
setup(name=name, | ||
description=description, | ||
version=__version__, | ||
long_description=readme, | ||
long_description_content_type="text/markdown", | ||
author="stac-utils", | ||
author_email='stac@radiant.earth', | ||
url='https://github.com/stac-utils/stactools.git', | ||
packages=find_namespace_packages(), | ||
py_modules=[ | ||
splitext(basename(path))[0] for path in glob('stactools/*.py') | ||
], | ||
include_package_data=False, | ||
install_requires=install_requires, | ||
license="Apache Software License 2.0", | ||
keywords=[ | ||
'stactools', 'psytac', 'corine', 'imagery', 'landcover', | ||
'land cover', 'catalog', 'STAC' | ||
]) |
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,16 @@ | ||
# flake8: noqa | ||
|
||
from stactools.corine.stac import create_item | ||
from stactools.corine.cog import create_cogs | ||
|
||
import stactools.core | ||
|
||
stactools.core.use_fsspec() | ||
|
||
|
||
def register_plugin(registry): | ||
# Register subcommands | ||
|
||
from stactools.corine import commands | ||
|
||
registry.register_subcommand(commands.create_corine_command) |
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,73 @@ | ||
import logging | ||
import os | ||
from subprocess import Popen, PIPE, STDOUT | ||
|
||
import pystac | ||
from shapely.geometry import shape | ||
|
||
from stactools.corine.constants import (ITEM_COG_IMAGE_NAME, | ||
ITEM_TIF_IMAGE_NAME) | ||
from stactools.core.projection import reproject_geom | ||
|
||
logger = logging.getLogger(__name__) | ||
|
||
|
||
def call(command): | ||
def log_subprocess_output(pipe): | ||
for line in iter(pipe.readline, b''): # b'\n'-separated lines | ||
logger.info(line.decode("utf-8").strip('\n')) | ||
|
||
process = Popen(command, stdout=PIPE, stderr=STDOUT) | ||
with process.stdout: | ||
log_subprocess_output(process.stdout) | ||
return process.wait() # 0 means success | ||
|
||
|
||
def cogify(input_path, output_path): | ||
call([ | ||
'gdal_translate', '-of', 'COG', '-co', 'compress=deflate', input_path, | ||
output_path | ||
]) | ||
|
||
|
||
def _create_cog(item, cog_directory): | ||
geom = item.geometry | ||
crs = item.ext.projection.epsg | ||
reprojected_geom = reproject_geom('epsg:4326', crs, geom) | ||
bounds = shape(reprojected_geom).bounds | ||
print(bounds) | ||
|
||
tif_asset = item.assets.get(ITEM_TIF_IMAGE_NAME) | ||
cogify(tif_asset.href, cog_directory) | ||
|
||
return cog_directory | ||
|
||
|
||
def create_cogs(item, cog_directory=None): | ||
"""Create COGs from the HDF asset contained in the passed in STAC item. | ||
Args: | ||
item (pystac.Item): CORINE Item that contains an asset | ||
with key equal to stactools.corine.constants.ITEM_METADATA_NAME, | ||
which will be converted to COGs. | ||
cog_directory (str): A URI of a directory to store COGs. This will be used | ||
in conjunction with the file names based on the COG asset to store | ||
the COG data. If not supplied, the directory of the Item's self HREF | ||
will be used. | ||
Returns: | ||
pystac.Item: The same item, mutated to include assets for the | ||
new COGs. | ||
""" | ||
if cog_directory is None: | ||
cog_directory = os.path.dirname(item.get_self_href()) | ||
|
||
cog_href = os.path.join(cog_directory, '{}-cog.tif'.format(item.id)) | ||
_create_cog(item, cog_href) | ||
|
||
asset = pystac.Asset(href=cog_href, | ||
media_type=pystac.MediaType.COG, | ||
roles=['data'], | ||
title='Raster Dataset') | ||
|
||
item.assets[ITEM_COG_IMAGE_NAME] = asset |
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,51 @@ | ||
import logging | ||
import os | ||
|
||
import click | ||
|
||
from stactools.corine import stac, cog | ||
|
||
logger = logging.getLogger(__name__) | ||
|
||
|
||
def create_corine_command(cli): | ||
"""Creates a command group for commands working with | ||
CORINE Land Cover data. | ||
""" | ||
@cli.group('corine', | ||
short_help=("Commands for working with " | ||
"CORINE Land Cover data.")) | ||
def corine(): | ||
pass | ||
|
||
@corine.command('create-item', | ||
short_help='Create a STAC Item from a CORINE metadata file' | ||
) | ||
@click.argument('metadata_href') | ||
@click.argument('dst') | ||
@click.option('-c', | ||
'--cogify', | ||
is_flag=True, | ||
help='Convert the tif into COG.') | ||
def create_item_command(metadata_href, dst, cogify): | ||
"""Creates a STAC Item based on metadata from an tif | ||
CORINE Land Cover file. | ||
METADATA_REF is the CORINE Land Cover metadata file. The | ||
tif file will be located in the same directory as that of METADATA_REF. | ||
DST is directory that a STAC Item JSON file will be created | ||
in. This will have a filename that matches the ID, which will | ||
is the name of the METADATA_REF, without it's file extension. | ||
""" | ||
|
||
item = stac.create_item(metadata_href) | ||
|
||
item_path = os.path.join(dst, '{}.json'.format(item.id)) | ||
item.set_self_href(item_path) | ||
|
||
if cogify: | ||
cog.create_cogs(item) | ||
|
||
item.save_object() | ||
|
||
return corine |
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,11 @@ | ||
import pystac | ||
|
||
provider_name = 'European Environment Agency (EEA) under the framework of the Copernicus programme' | ||
|
||
COPERNICUS_PROVIDER = pystac.Provider(name=provider_name, | ||
url=('http://www.eea.europa.eu'), | ||
roles=['producer', 'licensor']) | ||
|
||
ITEM_COG_IMAGE_NAME = 'cog_image' | ||
ITEM_TIF_IMAGE_NAME = 'tif_image' | ||
ITEM_METADATA_NAME = 'metadata' |
Oops, something went wrong.