예제 #1
0
def create_footprints(csv_row):
    """Extract footprint from a Landsat 8 csv row

    Args:
        csv_row (dict): dictionary representation of a row in scene list csv

    Returns:
        Footprint
    """
    src_proj = Proj(init='epsg:4326')
    ll = (csv_row['lowerLeftCornerLongitude'],
          csv_row['lowerLeftCornerLatitude'])
    lr = (csv_row['lowerRightCornerLongitude'],
          csv_row['lowerRightCornerLatitude'])
    ul = (csv_row['upperLeftCornerLongitude'],
          csv_row['upperLeftCornerLatitude'])
    ur = (csv_row['upperRightCornerLongitude'],
          csv_row['upperRightCornerLatitude'])
    src_coords = [ll, lr, ur, ul]

    min_x = min([coord[0] for coord in src_coords])
    min_y = min([coord[1] for coord in src_coords])
    max_x = max([coord[0] for coord in src_coords])
    max_y = max([coord[1] for coord in src_coords])

    transformed_coords = [[[
        transform(src_proj, target_proj, coord[0], coord[1])
        for coord in src_coords
    ]]]

    data_geojson = {'type': 'MultiPolygon', 'coordinates': transformed_coords}
    data_footprint = Footprint(organization, data_geojson)

    transformed_tile_coords = [[[
        transform(src_proj, target_proj, coord[0], coord[1])
        for coord in [(min_x, min_y), (max_x, min_y), (max_x,
                                                       max_y), (min_x, max_y)]
    ]]]
    tile_geojson = {
        'type': 'MultiPolygon',
        'coordinates': transformed_tile_coords
    }
    tile_footprint = Footprint(organization, tile_geojson)

    return tile_footprint, data_footprint
예제 #2
0
def footprint_from_key(tileinfo, key):
    geom = tileinfo[key]
    coords = geom['coordinates'][0]
    src_proj = get_src_proj(geom['crs']['properties']['name'])
    transformed_coords = [[[
        transform(src_proj, target_proj, coord[0], coord[1])
        for coord in coords
    ]]]
    return Footprint(organization, transformed_coords)
예제 #3
0
def extract_footprints(organization_id, tif_path):
    """Performs all actions to extract polygon from a kayak scene

    Args:
        organization_id (str): organization footprints belong to
        tif_path (str): path to tif to extract polygons from

    Returns:
        tuple
    """
    logger.info('Beginning process to extract footprint for image:%s',
                tif_path)
    with get_tempdir() as temp_dir:

        _, resampled_tif_path = tempfile.mkstemp(suffix='.TIF', dir=temp_dir)

        with rasterio.open(tif_path) as src:
            y, x = src.shape

            aspect = y / float(x)
        x_size = 512
        y_size = int(512 * aspect)

        # Resample to a max width of 512
        cmd = [
            'gdal_translate',
            tif_path,
            resampled_tif_path,
            '-outsize',
            str(x_size),
            str(y_size),
        ]
        logger.info('Running GDAL command: %s', ' '.join(cmd))

        subprocess.check_call(cmd)

        tile_mask_tif_path, data_mask_tif_path = create_tif_mask(
            temp_dir, resampled_tif_path)
        data_footprint = extract_polygon(data_mask_tif_path)
        tile_footprint = extract_polygon(tile_mask_tif_path)

        return (Footprint(organization_id, tile_footprint),
                Footprint(organization_id, data_footprint))
예제 #4
0
def footprint_from_key(tileinfo, key):
    geom = tileinfo[key]
    coords = geom['coordinates'][0]
    src_proj = get_src_proj(geom['crs']['properties']['name'])
    transformed_coords = [[[
        transform(src_proj, target_proj, coord[0], coord[1])
        for coord in coords
    ]]]
    geojson = {"type": "MultiPolygon", "coordinates": transformed_coords}
    return Footprint(organization, geojson)
예제 #5
0
def extract_footprints(organization_id, tif_path):
    """Performs all actions to extract polygon from a kayak scene

    Args:
        organization_id (str): organization footprints belong to
        tif_path (str): path to tif to extract polygons from

    Returns:
        tuple
    """
    logger.info('Beginning process to extract footprint for image:%s',
                tif_path)

    with get_tempdir() as temp_dir:
        tile_mask_tif_path, data_mask_tif_path = create_tif_mask(
            temp_dir, tif_path)
        data_footprint = extract_polygon(data_mask_tif_path)
        tile_footprint = extract_polygon(tile_mask_tif_path)
        return (Footprint(organization_id, tile_footprint),
                Footprint(organization_id, data_footprint))
예제 #6
0
def extract_footprints(tif_path):
    """Performs all actions to extract polygon from a kayak scene

    Args:
        tif_path (str): path to tif to extract polygons from

    Returns:
        tuple
    """
    logger.info('Beginning process to extract footprint for image:%s',
                tif_path)
    with get_tempdir() as temp_dir:

        _, resampled_tif_path = tempfile.mkstemp(suffix='.TIF', dir=temp_dir)
        _, warped_path = tempfile.mkstemp(suffix='.TIF', dir=temp_dir)
        _, geojson_path = tempfile.mkstemp(suffix='.GEOJSON', dir=temp_dir)

        with rasterio.open(tif_path) as src:
            y, x = src.shape
            aspect = y / float(x)
            x_size = 512
            y_size = int(512 * aspect)

        resample_cmd = [
            'gdal_translate', tif_path, resampled_tif_path, '-outsize',
            str(x_size),
            str(y_size)
        ]
        warp_cmd = [
            'gdalwarp', '-co', 'compress=LZW', '-dstnodata', '0', '-dstalpha',
            '-t_srs', 'epsg:4326', resampled_tif_path, warped_path
        ]
        polygonize_cmd = [
            'gdal_polygonize.py', '-b', 'mask', warped_path, '-f', 'GEOJSON',
            geojson_path
        ]

        subprocess.check_call(resample_cmd)
        subprocess.check_call(warp_cmd)
        subprocess.check_call(polygonize_cmd)
        with open(geojson_path, 'r+') as fh:
            geojson = json.load(fh)

        data_footprint = [
            feature['geometry']['coordinates']
            for feature in geojson['features']
            if feature['properties']['DN'] == 255
        ]

        xs = []
        ys = []

        for area in data_footprint:
            xst, yst = zip(*area[0])
            xs += xst
            ys += yst

        xmin = min(xs)
        xmax = max(xs)
        ymin = min(ys)
        ymax = max(ys)

        tile_footprint = [[[[xmin, ymin], [xmax, ymin], [xmax, ymax],
                            [xmin, ymax], [xmin, ymin]]]]

        return (Footprint(tile_footprint), Footprint(data_footprint))
예제 #7
0
def create_planet_scene(planet_feature,
                        datasource,
                        organization_id,
                        planet_key,
                        ingest_status=IngestStatus.TOBEINGESTED,
                        visibility=Visibility.PRIVATE,
                        tags=[],
                        owner=None,
                        sceneType="AVRO"):
    """Create a Raster Foundry scene from Planet scenes

    Args:
        planet_key (str): API auth key for planet API
        planet_feature (dict): json response from planet API client
        datasource (str): UUID of the datasource this scene belongs to
        organization_id (str): UUID of the organization that owns the scene
        visibility (Visibility): visibility for created scene
        tags (str[]): list of tags to attach to the created scene
        owner (str): user ID of the user who owns the scene

    Returns:
        Scene
    """

    props = planet_feature['properties']
    datasource = datasource
    name = planet_feature['id']
    acquisitionDate = props['acquired']
    cloudCover = props['cloud_cover']
    ingestSizeBytes = 0  # TODO
    visibility = visibility
    tags = tags
    dataFootprint = planet_feature['geometry']['coordinates']

    scene_kwargs = {
        'sunAzimuth':
        props['sun_azimuth'],
        'sunElevation':
        props['sun_elevation'],
        'cloudCover':
        cloudCover,
        'acquisitionDate':
        acquisitionDate,
        'id':
        str(uuid.uuid4()),
        'thumbnails':
        None,
        'tileFootprint':
        Footprint(organization_id, bbox_from_planet_feature(planet_feature)),
        'dataFootprint':
        Footprint(organization_id, [planet_feature['geometry']['coordinates']])
    }

    images = [
        create_geotiff_image(organization_id,
                             planet_feature['added_props']['localPath'],
                             planet_feature['added_props']['s3Location'],
                             scene=scene_kwargs['id'],
                             visibility=visibility,
                             owner=owner)
    ]

    scene = Scene(organization_id,
                  ingestSizeBytes,
                  visibility,
                  tags,
                  datasource,
                  props,
                  name,
                  JobStatus.QUEUED,
                  JobStatus.QUEUED,
                  ingest_status, [],
                  owner=owner,
                  images=images,
                  sceneType=sceneType,
                  **scene_kwargs)

    thumbnail_url = planet_feature['_links']['thumbnail']
    scene.thumbnails = [
        get_planet_thumbnail(organization_id, thumbnail_url, planet_key,
                             scene.id)
    ]

    return scene
예제 #8
0
def create_geotiff_scene(tif_path,
                         datasource,
                         acquisitionDate=None,
                         cloudCover=0,
                         visibility=Visibility.PRIVATE,
                         tags=[],
                         sceneMetadata=None,
                         name=None,
                         thumbnailStatus=JobStatus.QUEUED,
                         boundaryStatus=JobStatus.QUEUED,
                         ingestStatus=IngestStatus.TOBEINGESTED,
                         metadataFiles=[],
                         owner=None,
                         sceneType="COG",
                         **kwargs):
    """Returns scenes that can be created via API given a local path to a geotiff.

    Does not create Images because those require a Source URI, which this doesn't know about. Use
    create_geotiff_scene from a higher level of code that knows about where things are located
    remotely and then add those Images to the Scene that this function returns.

    Tries to extract metadata from the GeoTIFF where possible, but can also accept parameter
    overrides. Order of preference is as follows:
        1) Kwargs
        2) GeoTiff Value / Dynamic value (e.g. azimuth calculated from capture location / time)
        3) Default values

    Args:
        tif_path (str): Local path to GeoTIFF file to use.
        datasource (str): Name describing the source of the data
        **kwargs: Any remaining keyword arguments will override the values being passed to the Scene
            constructor. If

    Returns:
        List[Scene]
    """
    logger.info("Generating Scene from %s", tif_path)

    # Start with default values
    sceneMetadata = sceneMetadata if sceneMetadata else get_geotiff_metadata(
        tif_path)
    name = name if name else get_geotiff_name(tif_path)

    sceneKwargs = {
        "sunAzimuth":
        None,  # TODO: Calculate from acquisitionDate and tif center.
        "sunElevation": None,  # TODO: Same
        "cloudCover": cloudCover,
        "acquisitionDate": acquisitionDate,
        "id": str(uuid.uuid4()),
        "thumbnails": None,
    }
    # Override defaults with kwargs
    sceneKwargs.update(kwargs)
    data_footprint = complex_footprint(tif_path)
    tile_footprint = MultiPolygon(
        [Polygon.from_bounds(*data_footprint.bounds)])

    # Construct Scene
    scene = Scene(
        visibility,
        tags,
        datasource,
        sceneMetadata,
        name,
        thumbnailStatus,
        boundaryStatus,
        ingestStatus,
        metadataFiles,
        owner=owner,
        sceneType=sceneType,
        dataFootprint=Footprint(mapping(data_footprint)["coordinates"]),
        tileFootprint=Footprint(mapping(tile_footprint)["coordinates"]),
        **sceneKwargs)

    return scene