Skip to content
Snippets Groups Projects
generate_tiles.py 3.38 KiB
#!/usr/bin/env python3

import os
import sys
import warnings
import logging
import subprocess
import shutil

import tile_index

LOG = logging.getLogger(__name__)


def group_files(products, input_files):
    """Group input geotiff files by product."""
    groups = {}
    for prod in products:
        prods_files = [f for f in input_files if prod in f]
        if prods_files:
            groups[prod] = prods_files
    if len(groups) != len(products):
        warnings.warn("Not all product geotiffs were provided.")
    return groups


def remap_to_lonlat(itif, otif):
    """Remap a single geotiff by calling gdalwarp."""
    try:
        subprocess.run(['gdalwarp', '-multi', '-wo', 'NUM_THREADS=ALL_CPUS', '-t_srs', 'EPSG:4326', itif, otif], check=True)
    except subprocess.CalledProcessError:
        LOG.error("Could not remap geotiff %s -> %s" % (itif, otif))
        return None
    return otif


def remap_tifs(input_tifs, out_dir, remap_suffix):
    """Remap all input geotiffs to EPSG:4326."""
    for itif in input_tifs:
        ifn = os.path.basename(itif)
        otif = os.path.join(out_dir, ifn.replace('.tif', remap_suffix))
        otif = remap_to_lonlat(itif, otif)
        if otif is not None:
            yield otif


def link_or_copy(input_tifs, out_dir):
    """Hardlink input tifs to output directory."""
    for prod_file in input_tifs:
        out_file = os.path.join(out_dir, os.path.basename(prod_file))
        try:
            os.link(prod_file, out_file)
        except OSError:
            # on different mounts probably?
            shutil.copy2(prod_file, out_file)
        yield out_file


def main():
    import argparse
    parser = argparse.ArgumentParser(description="Take input geotiffs and generate mapserver compatible tiles.")
    parser.add_argument('--remap', action='store_true',
                        help="Remap input geotiffs to EPSG:4326")
    parser.add_argument('--remap-suffix', default='_LL.tif',
                        help="Replace 'tif' with provided suffix when geotiffs are remapped.")
    parser.add_argument('-p', '--products', nargs="*",
                        help="Product names to group together in each "
                             "'layer'. Product name must be in the filename.")
    parser.add_argument('--shape-file', default='{product}.shp',
                        help="Shapefile filename pattern to use and placed in the output directory. (default: '{product}.shp')")
    parser.add_argument('out_dir',
                        help="Output path to save tile information to (ex. '/data/tiles/{product}')")
    parser.add_argument('input_files', nargs="+",
                        help="Input geotiffs to generate tiles for (separate from product lists with '--')")
    args = parser.parse_args()

    groups = group_files(args.products, args.input_files)
    for prod, prod_files in groups.items():
        out_dir = args.out_dir.format(product=prod)
        os.makedirs(out_dir, exist_ok=True)
        shp_fn = args.shape_file.format(product=prod)
        shp_pathname = os.path.join(out_dir, shp_fn)

        if args.remap:
            # remap if needed
            prod_files = list(remap_tifs(prod_files, out_dir, args.remap_suffix))
        else:
            # hardlink if needed
            prod_files = list(link_or_copy(prod_files, out_dir))

        # create shape file
        tile_index.index(prod_files, shp_pathname)



if __name__ == "__main__":
    sys.exit(main())