mirror of
https://github.com/rasterio/rasterio.git
synced 2026-01-25 14:10:17 +00:00
136 lines
5.0 KiB
Python
136 lines
5.0 KiB
Python
#!/usr/bin/env python
|
|
|
|
"""Rasterio command line interface"""
|
|
|
|
import argparse
|
|
import json
|
|
import logging
|
|
import pprint
|
|
import sys
|
|
import warnings
|
|
|
|
import click
|
|
|
|
import rasterio
|
|
from rasterio.tool import main
|
|
from rasterio.warp import transform
|
|
|
|
warnings.simplefilter('default')
|
|
|
|
def configure_logging(verbosity):
|
|
log_level = max(10, 30 - 10*verbosity)
|
|
logging.basicConfig(stream=sys.stderr, level=log_level)
|
|
|
|
# The CLI command group.
|
|
@click.group(help="Rasterio command line interface.")
|
|
@click.option('--verbose', '-v', count=True, help="Increase verbosity.")
|
|
@click.option('--quiet', '-q', count=True, help="Decrease verbosity.")
|
|
@click.pass_context
|
|
def cli(ctx, verbose, quiet):
|
|
verbosity = verbose - quiet
|
|
configure_logging(verbosity)
|
|
ctx.obj = {}
|
|
ctx.obj['verbosity'] = verbosity
|
|
|
|
# Commands are below.
|
|
#
|
|
# Command bodies less than ~20 lines, e.g. info() below, can go in this
|
|
# module. Longer ones, e.g. insp() shall call functions imported from
|
|
# rasterio.tool.
|
|
|
|
# Info command.
|
|
@cli.command(short_help="Print information about a data file.")
|
|
@click.argument('src_path', type=click.Path(exists=True))
|
|
@click.option('--meta', 'aspect', flag_value='meta', default=True,
|
|
help="Show data file structure (default).")
|
|
@click.option('--tags', 'aspect', flag_value='tags',
|
|
help="Show data file tags.")
|
|
@click.option('--indent', default=2, type=int,
|
|
help="Indentation level for pretty printed output")
|
|
@click.option('--namespace', help="Select a tag namespace.")
|
|
@click.pass_context
|
|
def info(ctx, src_path, aspect, indent, namespace):
|
|
verbosity = ctx.obj['verbosity']
|
|
logger = logging.getLogger('rio')
|
|
try:
|
|
with rasterio.drivers(CPL_DEBUG=verbosity>2):
|
|
with rasterio.open(src_path) as src:
|
|
if aspect == 'meta':
|
|
pprint.pprint(src.meta, indent=indent)
|
|
elif aspect == 'tags':
|
|
pprint.pprint(src.tags(ns=namespace), indent=indent)
|
|
sys.exit(0)
|
|
except Exception:
|
|
logger.exception("Failed. Exception caught")
|
|
sys.exit(1)
|
|
|
|
# Insp command.
|
|
@cli.command(short_help="Open a data file and start an interpreter.")
|
|
@click.argument('src_path', type=click.Path(exists=True))
|
|
@click.option('--mode', type=click.Choice(['r', 'r+']), default='r', help="File mode (default 'r').")
|
|
@click.pass_context
|
|
def insp(ctx, src_path, mode):
|
|
verbosity = ctx.obj['verbosity']
|
|
try:
|
|
with rasterio.drivers(CPL_DEBUG=verbosity>2):
|
|
with rasterio.open(src_path, mode) as src:
|
|
main(
|
|
"Rasterio %s Interactive Inspector (Python %s)\n"
|
|
'Type "src.meta", "src.read_band(1)", or "help(src)" '
|
|
'for more information.' % (
|
|
rasterio.__version__,
|
|
'.'.join(map(str, sys.version_info[:3]))),
|
|
src)
|
|
sys.exit(0)
|
|
except Exception:
|
|
logger.exception("Failed. Exception caught")
|
|
sys.exit(1)
|
|
|
|
# Bounds command.
|
|
@cli.command(short_help="Write bounding boxes to stdout as GeoJSON.",
|
|
help="""
|
|
Write bounding boxes to stdout as GeoJSON for use with, e.g., geojsonio
|
|
|
|
$ rio bounds *.tif | geojsonio
|
|
""")
|
|
@click.argument('src_paths', nargs=-1, type=click.Path(exists=True))
|
|
@click.option('--precision', type=int, default=6,
|
|
help="Decimal precision of coordinates.")
|
|
@click.option('--indent', default=None, type=int,
|
|
help="Indentation level for JSON output")
|
|
@click.option('--projected/--geographic', default=False,
|
|
help="Output in projected coordinates (default is geographic).")
|
|
@click.pass_context
|
|
def bounds(ctx, src_paths, precision, indent, projected):
|
|
verbosity = ctx.obj['verbosity']
|
|
logger = logging.getLogger('rio')
|
|
try:
|
|
collection = {'type': 'FeatureCollection'}
|
|
features = []
|
|
with rasterio.drivers(CPL_DEBUG=verbosity>2):
|
|
for i, path in enumerate(src_paths):
|
|
with rasterio.open(path) as src:
|
|
bounds = src.bounds
|
|
xs = [bounds[0], bounds[2]]
|
|
ys = [bounds[1], bounds[3]]
|
|
if not projected:
|
|
xs, ys = transform(
|
|
src.crs, {'init': 'epsg:4326'}, xs, ys)
|
|
xs = [round(v, precision) for v in xs]
|
|
ys = [round(v, precision) for v in ys]
|
|
features.append(
|
|
{'type': 'Feature', 'geometry':
|
|
{'type': 'Polygon', 'coordinates': [
|
|
[[xs[0], ys[0]], [xs[1], ys[0]], [xs[1], ys[1]],
|
|
[xs[0], ys[1]], [xs[0], ys[0]] ]]},
|
|
'properties': {'id': str(i), 'title': path} })
|
|
collection['features'] = features
|
|
print(json.dumps(collection, indent=indent, sort_keys=True))
|
|
sys.exit(0)
|
|
except Exception:
|
|
logger.exception("Failed. Exception caught")
|
|
sys.exit(1)
|
|
|
|
if __name__ == '__main__':
|
|
cli()
|