Example #1
0
def download_crops(imgs,
                   aoi,
                   mirror,
                   out_dir,
                   parallel_downloads,
                   timeout=600):
    """
    Download a timeseries of crops with GDAL VSI feature.

    Args:
        imgs (list): list of images
        aoi (geojson.Polygon): area of interest
        mirror (str): either 'peps', 'aws' or 'scihub'
        out_dir (str): path where to store the downloaded crops
        parallel_downloads (int): number of parallel downloads
    """
    print('Building {} {} download urls...'.format(len(imgs), mirror), end=' ')
    if mirror == 'scihub':
        parallel.run_calls(
            s1_metadata_parser.Sentinel1Image.build_scihub_links,
            imgs,
            pool_type='threads',
            nb_workers=parallel_downloads)
    else:
        parallel.run_calls(s1_metadata_parser.Sentinel1Image.build_s3_links,
                           imgs,
                           pool_type='threads',
                           timeout=timeout,
                           nb_workers=parallel_downloads)

    # convert aoi coords from (lon, lat) to UTM
    coords = utils.utm_bbx(
        aoi, r=60)  # round to multiples of 60m to match Sentinel-2 grid

    crops_args = []
    nb_removed = 0
    for img in imgs:

        if not img.urls[mirror]:  # then it cannot be downloaded
            nb_removed = nb_removed + 1
            continue

        for p in img.polarisations:
            fname = os.path.join(out_dir, '{}_{}.tif'.format(img.filename, p))
            crops_args.append((fname, img.urls[mirror][p], *coords))

    if nb_removed:
        print('Removed {} image(s) with invalid urls'.format(nb_removed))

    out_dir = os.path.abspath(os.path.expanduser(out_dir))
    os.makedirs(out_dir, exist_ok=True)
    print(
        'Downloading {} crops ({} images with 1 or 2 polarisations)...'.format(
            len(crops_args),
            len(imgs) - nb_removed),
        end=' ')
    parallel.run_calls(utils.crop_with_gdalwarp,
                       crops_args,
                       pool_type='processes',
                       nb_workers=parallel_downloads)
Example #2
0
def download(imgs, bands, aoi, mirror, out_dir, parallel_downloads):
    """
    Download a timeseries of crops with GDAL VSI feature.

    Args:
        imgs (list): list of images
        bands (list): list of bands
        aoi (geojson.Polygon): area of interest
        mirror (str): either 'aws' or 'gcloud'
        out_dir (str): path where to store the downloaded crops
        parallel_downloads (int): number of parallel downloads
    """
    coords = utils.utm_bbx(aoi)
    crops_args = []
    for img in imgs:
        for b in set(bands + ['BQA']):
            fname = os.path.join(out_dir, '{}_band_{}.tif'.format(img.filename, b))
            crops_args.append((fname, img.urls[mirror][b]))

    out_dir = os.path.abspath(os.path.expanduser(out_dir))
    os.makedirs(out_dir, exist_ok=True)
    print('Downloading {} crops ({} images with {} bands)...'.format(len(crops_args),
                                                                     len(imgs),
                                                                     len(bands) +1),
          end=' ')
    parallel.run_calls(utils.crop_with_gdal_translate, crops_args,
                       extra_args=(*coords,), pool_type='threads',
                       nb_workers=parallel_downloads)
Example #3
0
def download(imgs, bands, aoi, mirror, out_dir, parallel_downloads):
    """
    Download a timeseries of crops with GDAL VSI feature.

    Args:
        imgs (list): list of images
        bands (list): list of bands
        aoi (geojson.Polygon): area of interest
        mirror (str): either 'aws' or 'gcloud'
        out_dir (str): path where to store the downloaded crops
        parallel_downloads (int): number of parallel downloads
    """
    print('Building {} {} download urls...'.format(len(imgs), mirror), end=' ')
    if mirror == 'gcloud':
        parallel.run_calls(s2_metadata_parser.Sentinel2Image.build_gs_links,
                           imgs,
                           pool_type='threads',
                           nb_workers=parallel_downloads)
    else:
        parallel.run_calls(s2_metadata_parser.Sentinel2Image.build_s3_links,
                           imgs,
                           pool_type='threads',
                           nb_workers=parallel_downloads)

    crops_args = []
    nb_removed = 0
    for img in imgs:

        if not img.urls[mirror]:  # then it cannot be downloaded
            nb_removed = nb_removed + 1
            continue

        # convert aoi coords from (lon, lat) to UTM in the zone of the image
        coords = utils.utm_bbx(aoi, epsg=int(
            img.epsg), r=60)  # round to multiples of 60 (B01 resolution)

        for b in bands:
            fname = os.path.join(out_dir,
                                 '{}_band_{}.tif'.format(img.filename, b))
            crops_args.append((fname, img.urls[mirror][b], *coords))

    if nb_removed:
        print('Removed {} image(s) with invalid urls'.format(nb_removed))

    out_dir = os.path.abspath(os.path.expanduser(out_dir))
    os.makedirs(out_dir, exist_ok=True)
    print('Downloading {} crops ({} images with {} bands)...'.format(
        len(crops_args),
        len(imgs) - nb_removed, len(bands)),
          end=' ')
    parallel.run_calls(utils.rasterio_geo_crop,
                       crops_args,
                       extra_args=('UInt16', ),
                       pool_type='threads',
                       nb_workers=parallel_downloads)
Example #4
0
def download(imgs,
             bands,
             aoi,
             mirror,
             out_dir,
             parallel_downloads,
             no_crop=False,
             timeout=60):
    """
    Download a timeseries of crops with GDAL VSI feature.

    Args:
        imgs (list): list of images
        bands (list): list of bands
        aoi (geojson.Polygon): area of interest
        mirror (str): either 'aws' or 'gcloud'
        out_dir (str): path where to store the downloaded crops
        parallel_downloads (int): number of parallel downloads
        no_crop (bool): don't crop but instead download the original JP2 files
    """
    if mirror == "gcloud":
        parallel.run_calls(s2_metadata_parser.Sentinel2Image.build_gs_links,
                           imgs,
                           pool_type='threads',
                           verbose=False,
                           nb_workers=parallel_downloads,
                           timeout=timeout)
    elif mirror == "aws":
        parallel.run_calls(s2_metadata_parser.Sentinel2Image.build_s3_links,
                           imgs,
                           pool_type='threads',
                           verbose=False,
                           nb_workers=parallel_downloads,
                           timeout=timeout)
    else:
        raise ValueError(f"Unknown mirror {mirror}")

    crops_args = []
    nb_removed = 0
    for img in imgs:

        if not img.urls[mirror]:  # then it cannot be downloaded
            nb_removed = nb_removed + 1
            continue

        # convert aoi coords from (lon, lat) to UTM in the zone of the image
        coords = ()
        if aoi is not None:
            coords = utils.utm_bbx(aoi, epsg=int(
                img.epsg), r=60)  # round to multiples of 60 (B01 resolution)

        for b in bands:
            fname = os.path.join(out_dir,
                                 '{}_band_{}.tif'.format(img.filename, b))
            crops_args.append((fname, img.urls[mirror][b], *coords))

    if nb_removed:
        print('Removed {} image(s) with invalid urls'.format(nb_removed))

    out_dir = os.path.abspath(os.path.expanduser(out_dir))
    os.makedirs(out_dir, exist_ok=True)
    print('Downloading {} crops ({} images with {} bands)...'.format(
        len(crops_args),
        len(imgs) - nb_removed, len(bands)))

    if no_crop or (aoi is None):  # download original files
        for fname, url, *_ in crops_args:
            ext = url.split(".")[-1]  # jp2, TIF, ...
            utils.download(url, fname.replace(".tif", f".{ext}"))

    else:  # download crops
        parallel.run_calls(utils.rasterio_geo_crop,
                           crops_args,
                           pool_type='threads',
                           nb_workers=parallel_downloads)
Example #5
0
def get_time_series(aoi,
                    start_date=None,
                    end_date=None,
                    item_types=['PSScene3Band'],
                    asset_type='analytic',
                    out_dir='',
                    parallel_downloads=multiprocessing.cpu_count(),
                    clip_and_ship=True,
                    no_crop=False,
                    satellite_id=None,
                    item_id=None,
                    search_type='contains',
                    remove_duplicates=True):
    """
    Main function: crop and download Planet images.
    """
    # list available images
    items = search_planet.search(aoi,
                                 start_date,
                                 end_date,
                                 item_types=item_types,
                                 satellite_id=satellite_id,
                                 item_id=item_id,
                                 search_type=search_type,
                                 remove_duplicates=remove_duplicates)
    print('Found {} images'.format(len(items)))

    # list the requested asset for each available (and allowed) image
    print('Listing available {} assets...'.format(asset_type),
          flush=True,
          end=' ')
    assets = parallel.run_calls(get_item_asset_info,
                                items,
                                extra_args=(asset_type, ),
                                pool_type='threads',
                                nb_workers=parallel_downloads,
                                timeout=600)

    # remove 'None' (ie not allowed) assets and corresponding items
    items = [i for (i, a) in zip(items, assets) if a]
    assets = [a for a in assets if a]
    print('Have permissions for {} images'.format(len(items)))

    # activate the allowed assets
    print('Requesting activation of {} images...'.format(len(assets)),
          flush=True,
          end=' ')
    parallel.run_calls(request_activation,
                       assets,
                       pool_type='threads',
                       nb_workers=parallel_downloads,
                       timeout=600)

    # warn user about quota usage
    n = len(assets)
    if clip_and_ship:
        a = n * area.area(aoi)
    else:
        a = sum(area.area(i['geometry']) for i in items)
    print('Your current quota usage is {}'.format(get_quota()), flush=True)
    print('Downloading these {} images will increase it by {:.3f} kmĀ²'.format(
        n, a / 1e6),
          flush=True)

    # build filenames
    ext = 'zip' if clip_and_ship else 'tif'
    out_dir = os.path.abspath(os.path.expanduser(out_dir))
    fnames = [
        os.path.join(out_dir, '{}.{}'.format(fname_from_metadata(i), ext))
        for i in items
    ]

    if clip_and_ship:
        print('Requesting clip of {} images...'.format(len(assets)),
              flush=True,
              end=' ')
        clips = parallel.run_calls(request_clip,
                                   list(zip(items, assets)),
                                   extra_args=(aoi, ),
                                   pool_type='threads',
                                   nb_workers=parallel_downloads,
                                   timeout=3600)

        # remove clips that were rejected
        ok = [i for i, x in enumerate(clips) if x]
        clips = [clips[i] for i in range(len(clips)) if i in ok]
        fnames = [fnames[i] for i in range(len(fnames)) if i in ok]

        print('Downloading {} clips...'.format(len(clips)),
              end=' ',
              flush=True)
        parallel.run_calls(download_clip,
                           list(zip(clips, fnames)),
                           pool_type='threads',
                           nb_workers=parallel_downloads,
                           timeout=3600)

    elif no_crop:  # download full images
        os.makedirs(out_dir, exist_ok=True)
        print('Downloading {} full images...'.format(len(assets)), end=' ')
        parallel.run_calls(download_asset,
                           list(zip(fnames, assets)),
                           pool_type='threads',
                           nb_workers=parallel_downloads,
                           timeout=1200)
    else:
        if asset_type in [
                'udm', 'visual', 'analytic', 'analytic_dn', 'analytic_sr'
        ]:
            aoi_type = 'utm_rectangle'
            aoi = utils.utm_bbx(aoi)
        else:
            aoi_type = 'lonlat_polygon'

        # download crops with gdal through vsicurl
        os.makedirs(out_dir, exist_ok=True)
        print('Downloading {} crops...'.format(len(assets)), end=' ')
        parallel.run_calls(download_crop,
                           list(zip(fnames, assets)),
                           extra_args=(aoi, aoi_type),
                           pool_type='threads',
                           nb_workers=parallel_downloads,
                           timeout=300)

        # embed some metadata in the image files
        for f, img in zip(fnames,
                          items):  # embed some metadata as gdal geotiff tags
            if os.path.isfile(f):
                utils.set_geotif_metadata_items(
                    f, metadata_from_metadata_dict(img))