Exemple #1
0
    def test_case_3():
        root_cat = Catalog(id='test3', description='test case 3 catalog', title='test case 3 title')

        image_item = Item(id='imagery-item',
                          geometry=RANDOM_GEOM,
                          bbox=RANDOM_BBOX,
                          datetime=datetime.utcnow(),
                          properties={})

        image_item.add_asset('ortho', Asset(href='some/geotiff.tiff', media_type=MediaType.GEOTIFF))

        overviews = [LabelOverview('label', counts=[LabelCount('one', 1), LabelCount('two', 2)])]

        label_item = LabelItem(id='label-items',
                               geometry=RANDOM_GEOM,
                               bbox=RANDOM_BBOX,
                               datetime=datetime.utcnow(),
                               properties={},
                               label_description='ML Labels',
                               label_type='vector',
                               label_properties=['label'],
                               label_classes=[LabelClasses(classes=['one', 'two'], name='label')],
                               label_tasks=['classification'],
                               label_methods=['manual'],
                               label_overviews=overviews)
        label_item.add_source(image_item, assets=['ortho'])

        root_cat.add_item(image_item)
        root_cat.add_item(label_item)

        return root_cat
Exemple #2
0
    def test_full_copy_2(self):
        with TemporaryDirectory() as tmp_dir:
            cat = Catalog(id='test', description='test catalog')
            image_item = Item(id='Imagery',
                              geometry=RANDOM_GEOM,
                              bbox=RANDOM_BBOX,
                              datetime=datetime.utcnow(),
                              properties={})
            for key in ['ortho', 'dsm']:
                image_item.add_asset(
                    key, Asset(href='some/{}.tif'.format(key), media_type=MediaType.GEOTIFF))

            label_item = LabelItem(
                id='Labels',
                geometry=RANDOM_GEOM,
                bbox=RANDOM_BBOX,
                datetime=datetime.utcnow(),
                properties={},
                label_description='labels',
                label_type='vector',
                label_properties='label',
                label_classes=[LabelClasses(classes=['one', 'two'], name='label')],
                label_tasks=['classification'])
            label_item.add_source(image_item, assets=['ortho'])

            cat.add_items([image_item, label_item])

            cat.normalize_hrefs(os.path.join(tmp_dir, 'catalog-full-copy-2-source'))
            cat.save(catalog_type=CatalogType.ABSOLUTE_PUBLISHED)
            cat2 = cat.full_copy()
            cat2.normalize_hrefs(os.path.join(tmp_dir, 'catalog-full-copy-2-dest'))
            cat2.save(catalog_type=CatalogType.ABSOLUTE_PUBLISHED)

            self.check_catalog(cat, 'source')
            self.check_catalog(cat2, 'dest')
Exemple #3
0
def item(href: str,
         read_href_modifier: Optional[ReadHrefModifier] = None) -> Item:
    """Creates a STAC Item from the asset at the provided href.

    The `read_href_modifer` argument can be used to modify the href for the
    rasterio read, e.g. if you need to sign a url.

    This function is intentionally minimal in its signature and capabilities. If
    you need to customize your Item, do so after creation.

    This function sets:
    - id
    - geometry
    - bbox
    - datetime (to the time of item creation): you'll probably want to change this
    - the proj extension
        - either the EPSG code or, if not available, the WKT2
        - transform
        - shape
    - a single asset with key 'data'
        - asset href
        - asset roles to ['data']

    In particular, the datetime and asset media type fields most likely need to be updated.
    """
    id = os.path.splitext(os.path.basename(href))[0]
    if read_href_modifier:
        modified_href = read_href_modifier(href)
    else:
        modified_href = href
    with rasterio.open(modified_href) as dataset:
        crs = dataset.crs
        proj_bbox = dataset.bounds
        proj_transform = list(dataset.transform)[0:6]
        proj_shape = dataset.shape
    proj_geometry = shapely.geometry.mapping(shapely.geometry.box(*proj_bbox))
    geometry = stactools.core.projection.reproject_geom(crs,
                                                        'EPSG:4326',
                                                        proj_geometry,
                                                        precision=6)
    bbox = list(shapely.geometry.shape(geometry).bounds)
    item = Item(id=id,
                geometry=geometry,
                bbox=bbox,
                datetime=datetime.datetime.now(),
                properties={})

    projection = ProjectionExtension.ext(item, add_if_missing=True)
    epsg = crs.to_epsg()
    if epsg:
        projection.epsg = epsg
    else:
        projection.wkt2 = crs.to_wkt('WKT2')
    projection.transform = proj_transform
    projection.shape = proj_shape

    item.add_asset('data', Asset(href=href, roles=['data']))

    return item
Exemple #4
0
    def test_map_items_multiple_2(self):
        catalog = Catalog(id='test-1', description='Test1')
        item1 = Item(id='item1',
                     geometry=RANDOM_GEOM,
                     bbox=RANDOM_BBOX,
                     datetime=datetime.utcnow(),
                     properties={})
        item1.add_asset('ortho', Asset(href='/some/ortho.tif'))
        catalog.add_item(item1)
        kitten = Catalog(id='test-kitten',
                         description='A cuter version of catalog')
        catalog.add_child(kitten)
        item2 = Item(id='item2',
                     geometry=RANDOM_GEOM,
                     bbox=RANDOM_BBOX,
                     datetime=datetime.utcnow(),
                     properties={})
        item2.add_asset('ortho', Asset(href='/some/other/ortho.tif'))
        kitten.add_item(item2)

        def modify_item_title(item):
            item.title = 'Some new title'
            return item

        def create_label_item(item):
            # Assumes the GEOJSON labels are in the
            # same location as the image
            img_href = item.assets['ortho'].href
            label_href = '{}.geojson'.format(os.path.splitext(img_href)[0])
            label_item = Item(id='Labels',
                              geometry=item.geometry,
                              bbox=item.bbox,
                              datetime=datetime.utcnow(),
                              properties={})
            label_item.ext.enable(Extensions.LABEL)
            label_ext = label_item.ext.label
            label_ext.apply(label_description='labels',
                            label_type='vector',
                            label_properties=['label'],
                            label_classes=[
                                LabelClasses.create(classes=['one', 'two'],
                                                    name='label')
                            ],
                            label_tasks=['classification'])
            label_ext.add_source(item, assets=['ortho'])
            label_ext.add_geojson_labels(label_href)

            return [item, label_item]

        c = catalog.map_items(modify_item_title)
        c = c.map_items(create_label_item)
        new_catalog = c

        items = new_catalog.get_all_items()
        self.assertTrue(len(list(items)) == 4)
Exemple #5
0
    def test_case_3() -> Catalog:
        root_cat = Catalog(id="test3",
                           description="test case 3 catalog",
                           title="test case 3 title")

        image_item = Item(
            id="imagery-item",
            geometry=ARBITRARY_GEOM,
            bbox=ARBITRARY_BBOX,
            datetime=datetime.utcnow(),
            properties={},
        )

        image_item.add_asset(
            "ortho",
            Asset(href="some/geotiff.tiff", media_type=MediaType.GEOTIFF))

        overviews = [
            LabelOverview.create(
                "label",
                counts=[
                    LabelCount.create("one", 1),
                    LabelCount.create("two", 2)
                ],
            )
        ]

        label_item = Item(
            id="label-items",
            geometry=ARBITRARY_GEOM,
            bbox=ARBITRARY_BBOX,
            datetime=datetime.utcnow(),
            properties={},
        )

        LabelExtension.add_to(label_item)
        label_ext = LabelExtension.ext(label_item)
        label_ext.apply(
            label_description="ML Labels",
            label_type=LabelType.VECTOR,
            label_properties=["label"],
            label_classes=[
                LabelClasses.create(classes=["one", "two"], name="label")
            ],
            label_tasks=["classification"],
            label_methods=["manual"],
            label_overviews=overviews,
        )
        label_ext.add_source(image_item, assets=["ortho"])

        root_cat.add_item(image_item)
        root_cat.add_item(label_item)

        return root_cat
Exemple #6
0
def _add_cog_assets(
        item: pystac.Item,
        xml_metadata: XmlMetadata,
        vnir_cog_href: Optional[str],
        swir_cog_href: Optional[str],
        tir_cog_href: Optional[str],
        read_href_modifier: Optional[ReadHrefModifier] = None) -> None:

    pointing_angles = xml_metadata.pointing_angles

    sensors_to_hrefs = {
        VNIR_SENSOR: vnir_cog_href,
        SWIR_SENSOR: swir_cog_href,
        TIR_SENSOR: tir_cog_href
    }

    def title_for(sensor):
        return f'{sensor} Swath data'

    sensors_to_bands = get_sensors_to_bands()

    for sensor in ASTER_SENSORS:
        if sensors_to_hrefs[sensor] is None:
            logger.warning(f'Skipping {sensor} COG')
            continue

        cog_href = sensors_to_hrefs[sensor]
        sensor_asset = pystac.Asset(href=cog_href,
                                    media_type=pystac.MediaType.COG,
                                    roles=['data'],
                                    title=title_for(sensor))

        # Set bands
        item.ext.eo.set_bands(sensors_to_bands[sensor], sensor_asset)

        # Set view off_nadir
        if sensor in pointing_angles:
            item.ext.view.off_nadir = abs(pointing_angles[sensor])

        # Open COG headers to get proj info
        cog_read_href = cog_href
        if read_href_modifier:
            cog_read_href = read_href_modifier(cog_read_href)

        with rio.open(cog_read_href) as ds:
            image_shape = list(ds.shape)
            proj_bbox = list(ds.bounds)
            transform = list(ds.transform)

            item.ext.projection.set_shape(image_shape, sensor_asset)
            item.ext.projection.set_bbox(proj_bbox, sensor_asset)
            item.ext.projection.set_transform(transform, sensor_asset)

        item.add_asset(sensor, sensor_asset)
Exemple #7
0
def merge_items(source_item: pystac.Item,
                target_item: pystac.Item,
                move_assets: bool = False,
                ignore_conflicts: bool = False) -> None:
    """Merges the assets from source_item into target_item.

    The geometry and bounding box of the items will also be merged.

    Args:
        source_item (pystac.Item): The Item that will be merged into target_item.
            This item is not mutated in this operation.
        target_item (pystac.Item): The target item that will be merged into.
            This item will be mutated in this operation.
        move_assets (bool): If true, move the asset files alongside the target item.
        ignore_conflicts (bool): If True, assets with the same keys will not be merged,
            and asset files that would be moved to overwrite an existing file
            will not be moved. If False, either of these situations will throw an error.
    """
    target_item_href = target_item.get_self_href()
    if target_item_href is None:
        raise ValueError(
            f"Target Item {target_item.id} must have an HREF for merge")
    for key, asset in source_item.assets.items():
        if key in target_item.assets:
            if ignore_conflicts:
                continue
            else:
                raise Exception(
                    'Target item {} already has asset with key {}, '
                    'cannot merge asset in from {}'.format(
                        target_item, key, source_item))
        else:
            asset_href = asset.get_absolute_href()
            if asset_href is None:
                raise ValueError(
                    f"Asset {asset.title} must have an HREF for merge")
            if move_assets:
                new_asset_href = move_asset_file_to_item(
                    target_item, asset_href, ignore_conflicts=ignore_conflicts)
            else:
                if not is_absolute_href(asset.href):
                    asset_href = make_relative_href(asset_href,
                                                    target_item_href)
                new_asset_href = asset_href
            new_asset = asset.clone()
            new_asset.href = new_asset_href
            target_item.add_asset(key, new_asset)

    source_geom = shape(source_item.geometry)
    target_geom = shape(target_item.geometry)
    union_geom = source_geom.union(target_geom).buffer(0)
    target_item.geometry = mapping(union_geom)
    target_item.bbox = list(union_geom.bounds)
Exemple #8
0
def to_stac(item, in_tiff):

    item_out = Item(id=item.id,
                    geometry=item.geometry,
                    bbox=item.bbox,
                    datetime=item.datetime,
                    properties=item.properties)

    item_out.common_metadata.set_gsd(20)
    item_out.common_metadata.set_constellation('sentinel-1')
    item_out.common_metadata.set_mission('sentinel-1')
    item_out.common_metadata.set_platform('sentinel-1{}'.format(
        item.id[2:3].lower()))

    eo_item = extensions.eo.EOItemExt(item_out)

    band = 'sigma_db_vv '

    item_out.add_asset(key=band.lower(),
                       asset=Asset(href='{}_{}.tif'.format(
                           item.id, band.upper()),
                                   media_type=MediaType.GEOTIFF,
                                   properties={
                                       'sar:polarizations':
                                       band.lower().split('_')[1].upper()
                                   }))

    asset = eo_item.item.get_assets()[band.lower()]

    description = '{} for polarization channel {}{}'.format(
        band.lower().split('_')[0].title(),
        band.lower().split('_')[1].upper(),
        ' in {}'.format(band.lower().split('_')[2])
        if len(band.lower().split('_')) == 3 else '')

    stac_band = extensions.eo.Band.create(name=band.lower(),
                                          common_name=band.lower(),
                                          description=description)
    #bands.append(stac_band)

    eo_item.set_bands([stac_band], asset=asset)

    #eo_item.set_bands(bands)

    #eo_item.apply(bands)

    return item_out
Exemple #9
0
    def add_asset(self, item: pystac.Item, mtl_metadata: MtlMetadata,
                  base_href: str) -> None:
        asset = pystac.Asset(href=self.get_href(base_href),
                             media_type=self.media_type)
        if self.title:
            asset.title = self.title
        if self.description:
            asset.description = self.description

        # common_metadata

        if self.gsd is not None:
            item.common_metadata.set_gsd(self.gsd, asset)
        else:
            if self.is_sr or self.is_qa:
                sr_grd = mtl_metadata.sr_gsd
                if item.common_metadata.gsd != sr_grd:
                    item.common_metadata.set_gsd(sr_grd, asset)
            if self.is_thermal:
                thermal_grd = mtl_metadata.thermal_gsd
                if item.common_metadata.gsd != thermal_grd:
                    item.common_metadata.set_gsd(thermal_grd, asset)

        # eo

        if self.bands:
            asset.properties["eo:bands"] = [b.to_dict() for b in self.bands]

        # projection
        if self.is_sr or self.is_qa:
            item.ext.projection.set_shape(mtl_metadata.sr_shape, asset)
            item.ext.projection.set_transform(mtl_metadata.sr_transform, asset)
        if self.is_thermal:
            item.ext.projection.set_shape(mtl_metadata.thermal_shape, asset)
            item.ext.projection.set_transform(mtl_metadata.thermal_transform,
                                              asset)

        item.add_asset(self.key, asset)
def collection_add_sentinel_chips(collection,
                                  uri_list,
                                  sentinel_version,
                                  debug=False):
    """ Add sentinel images to a collection """
    if debug:
        uri_list = list(uri_list)[:10]
    for uri in uri_list:

        if not uri.endswith(".tif"):
            continue

        item_id = os.path.basename(uri).split(".")[0]
        country, event_id, *_ = item_id.split("_")
        params = {}
        params["id"] = item_id
        params["collection"] = collection
        params["properties"] = {
            "country": country,
            "event_id": event_id,
        }
        params["bbox"] = get_chip_bbox(uri, country, event_id)
        params["geometry"] = box(*params["bbox"]).__geo_interface__

        params["datetime"] = image_date_for_country(sentinel_version, country)

        # Create Tiff Item
        item = Item(**params)
        asset = Asset(href=uri,
                      title="GeoTiff",
                      media_type="image/tiff; application=geotiff")
        item.add_asset(key="image", asset=asset)
        SENTINEL_CHIP_ITEM_CACHE[sentinel_version.upper()][chip_cache_id(
            country, event_id)] = item
        collection.add_item(item)
        print("Collection {}: Added STAC Item {}".format(
            collection.id, item.id))
Exemple #11
0
def main(ctx, input_reference, s_expression, cbn):

    dump(ctx)

    item = get_item(os.path.join(input_reference, "catalog.json"))

    logging.info(f"Processing {item.id}")

    try:
        os.mkdir(item.id)
    except FileExistsError:
        pass

    cbn = cbn.replace(' ', '-')

    result = os.path.join(item.id, f"{cbn}.tif")

    logging.info(f"Apply {s_expression} to {item.id}")

    apply_s_expression(item=item, s_expression=s_expression, out_tif=result)

    logging.info("STAC")

    item_out = Item(
        id=item.id,
        geometry=item.geometry,
        bbox=item.bbox,
        datetime=item.datetime,
        properties=item.properties,
        stac_extensions=item.stac_extensions,
    )

    eo_item = extensions.eo.EOItemExt(item_out)

    asset_properties = dict()

    asset_properties["s-expression"] = s_expression

    asset = Asset(
        href=os.path.basename(result),
        media_type=MediaType.COG,
        roles=["data"],
        properties=asset_properties,
    )

    eo_bands = [
        extensions.eo.Band.create(
            name=cbn.lower(),
            common_name=cbn.lower(),
            description=f"{cbn.lower()} ({s_expression})",
        )
    ]

    eo_item.set_bands(eo_bands, asset=asset)

    item_out.add_asset(key=cbn.lower(), asset=asset)

    logging.info("STAC")

    cat = Catalog(id="catalog", description="s-expression")

    cat.add_items([item_out])

    cat.normalize_and_save(root_href="./",
                           catalog_type=CatalogType.SELF_CONTAINED)

    logging.info("Done!")
Exemple #12
0
def burned(pre_item, post_item, ndvi_threshold, ndwi_threshold):

    items = {}

    items["pre-event"] = pre_item
    items["post-event"] = post_item

    veg_indices = {}

    scl = {}

    for key, item in items.items():

        stack(
            item=item,
            bands=["B04", "B08", "B11", "SCL"],
            target_res=10,
            output_name=f"{key}.tif",
        )

        ndvi, ndwi = indices(f"{key}.tif")

        veg_indices[key] = {"ndvi": ndvi, "ndwi": ndwi}

        scl[key] = get_scl(f"{key}.tif")

        if key in ["pre-event"]:
            geotransform, georef = get_geo(f"{key}.tif")

        os.remove(f"{key}.tif")

    conditions = (
        (veg_indices["post-event"]["ndwi"] - veg_indices["pre-event"]["ndwi"])
        > float(ndwi_threshold)
    ) & (
        (veg_indices["post-event"]["ndvi"] - veg_indices["pre-event"]["ndvi"])
        > float(ndvi_threshold)
    ) & (
        scl["pre-event"] == 4
    ) | (
        scl["post-event"] == 4
    )

    height = scl["pre-event"].shape[1]
    width = scl["pre-event"].shape[0]

    burned = np.zeros((height, width), dtype=np.uint8)

    burned[conditions] = 1

    # free memory
    for key, _ in items.items():
        for indice, _ in veg_indices.items():
            veg_indices[key][indice] = None

    burned[
        np.where(
            (scl["pre-event"] == 0)
            | (scl["post-event"] == 0)
            | (scl["pre-event"] == 1)
            | (scl["post-event"] == 1)
            | (scl["pre-event"] == 5)
            | (scl["post-event"] == 5)
            | (scl["pre-event"] == 6)
            | (scl["post-event"] == 6)
            | (scl["pre-event"] == 7)
            | (scl["post-event"] == 7)
            | (scl["pre-event"] == 8)
            | (scl["post-event"] == 8)
            | (scl["pre-event"] == 9)
            | (scl["post-event"] == 9)
        )
    ] = 2

    output_name = "BURNED_AREA_{}".format(
        "_".join(
            [s2_item.datetime.strftime("%Y%m%d") for key, s2_item in items.items()]
        )
    )

    item_id = "burned-area"

    write_tif(
        burned,
        os.path.join(item_id, f"{output_name}.tif"),
        width,
        height,
        geotransform,
        georef,
    )

    item = Item(
        id=item_id,
        geometry=items["pre-event"].geometry,
        bbox=items["pre-event"].bbox,
        datetime=items["pre-event"].datetime,
        properties={},
    )

    item.add_asset(
        key="data",
        asset=Asset(
            href=os.path.join(".", f"{output_name}.tif"),
            media_type=MediaType.COG,
            title="Burned area analysis from Sentinel-2",
        ),
    )

    return item
Exemple #13
0
            image_item = Item(
                "flood_" + flood_id + "_chip_" + group_id,
                geometry=mapping(
                    Polygon([
                        [bounds.left, bounds.bottom],
                        [bounds.right, bounds.bottom],
                        [bounds.right, bounds.top],
                        [bounds.left, bounds.top],
                        [bounds.left, bounds.bottom],
                    ])),
                bbox=[bounds.bottom, bounds.left, bounds.top, bounds.right],
                datetime=start_time,
                properties={},
            )
            for asset in assets:
                image_item.add_asset(
                    asset.href.split("/")[-1].split(".")[0], asset)

            stac_items.append(image_item)
        aggregate_spatial_extent = SpatialExtent([[
            aggregate_bounds.bottom,
            aggregate_bounds.left,
            aggregate_bounds.top,
            aggregate_bounds.right,
        ]])
        aggregate_extent = Extent(aggregate_spatial_extent, temporal_extent)
        collection = Collection(
            flood_id,
            "Imagery coextensive with GLOFIMR flood {}".format(flood_id),
            extent=aggregate_extent,
        )
        for stac_item in stac_items:
Exemple #14
0
def main(ndvi_threshold, ndwi_threshold, pre_event, post_event):

    os.environ['PREFIX']='/opt/anaconda/envs/env_burned_area'
    
    os.environ['PROJ_LIB'] = os.path.join(os.environ['PREFIX'], 'share/proj')
    os.environ['GDAL_DATA'] = os.path.join(os.environ['PREFIX'], 'share/gdal')

    s2_item_pre = S2_stac_item(pre_event['value'])
    s2_item_post = S2_stac_item(post_event['value'])
    
    s2_items = dict()
    s2_items['pre-event'] = S2_stac_item(pre_event['value'])
    s2_items['post-event'] = S2_stac_item(post_event['value'])
    
    dates = []
    bboxes = []
    
    for index, item in enumerate([s2_item_pre.item, s2_item_post.item]):
        
        dates.append(item.datetime)
        bboxes.append(shape(item.geometry).bounds)
        
        logging.info('Stacking bands for input {}'.format(item.id))
        vrt_bands = []

        for band in ['B04', 'B08', 'B11', 'SCL']:

            vrt_bands.append('/vsicurl/{}'.format(item.assets[band].get_absolute_href()))

        vrt = '{}.vrt'.format('pre_event' if index == 0 else 'post_event')
        tif = '{}.tif'.format('pre_event' if index == 0 else 'post_event')

        logging.info('Build vrt for {}'.format(item.id))

        ds = gdal.BuildVRT(vrt,
                           vrt_bands,
                           srcNodata=0,
                           xRes=10, 
                           yRes=10,
                           separate=True)
        ds.FlushCache()


        logging.info('Translate {}'.format(item.id))

        gdal.Translate(tif,
                       vrt,
                       outputType=gdal.GDT_UInt16)

        os.remove(vrt)
    
    ds = gdal.Open('pre_event.tif')

    pre_b04 = ds.GetRasterBand(1).ReadAsArray()
    pre_b08 = ds.GetRasterBand(2).ReadAsArray()
    pre_b11 = ds.GetRasterBand(3).ReadAsArray()
    pre_scl = ds.GetRasterBand(4).ReadAsArray()

    ds = None

    os.remove('pre_event.tif')

    ds = gdal.Open('post_event.tif')

    post_b04 = ds.GetRasterBand(1).ReadAsArray()
    post_b08 = ds.GetRasterBand(2).ReadAsArray()
    post_b11 = ds.GetRasterBand(3).ReadAsArray()
    post_scl = ds.GetRasterBand(4).ReadAsArray()

    width = ds.RasterXSize
    height = ds.RasterYSize

    input_geotransform = ds.GetGeoTransform()
    input_georef = ds.GetProjectionRef()

    ds = None

    os.remove('post_event.tif')
    
    gain = 10000

    pre_ndwi2 = (pre_b08 / gain - pre_b11 / gain) / (pre_b08 / gain  + pre_b11 / gain)
    post_ndwi2 = (post_b08 / gain - post_b11 / gain) / (post_b08 / gain + post_b11 / gain)

    pre_b11 = None
    post_b11 = None

    pre_ndvi = (pre_b08 / gain - pre_b04 / gain) / (pre_b08 / gain  + pre_b04 / gain)
    post_ndvi = (post_b08 / gain - post_b04 / gain) / (post_b08 / gain + post_b04 / gain)

    pre_b04 = None
    post_b04 = None

    pre_b08 = None
    post_b08 = None

    conditions = (((post_ndwi2 - pre_ndwi2) > float(ndwi_threshold['value'])) & ((post_ndvi - pre_ndvi) > float(ndvi_threshold['value'])) & (pre_scl == 4) | (post_scl == 4))  

    burned = np.zeros((height, width), dtype=np.uint8) 

    burned[conditions] = 1

    pre_ndwi2 = None
    post_ndwi2 = None

    pre_ndvi = None
    post_ndvi = None

    burned[np.where((pre_scl == 0) | (post_scl == 0) | (pre_scl == 1) | (post_scl == 1) | (pre_scl == 5) | (post_scl == 5) | (pre_scl == 6) | (post_scl == 6) | (pre_scl == 7) | (post_scl == 7) | (pre_scl == 8) | (post_scl == 8) | (pre_scl == 9) | (post_scl == 9))] = 2 
    
    
    logging.info('Write output product')
    
    output_name = 'S2_BURNED_AREA_{}'.format('_'.join([d.strftime("%Y%m%d") for d in dates])) 

    write_tif(burned, '{}.tif'.format(output_name), width, height, input_geotransform, input_georef)

    logging.info('Output catalog')

    catalog = Catalog(id='catalog', description='Results')

    catalog.clear_items()
    catalog.clear_children()

    result_titles = dict()

    result_titles[output_name] = {'title': 'Burned area analysis from Sentinel-2',
                                  'media_type': MediaType.COG}



    items = []

    for key, value in result_titles.items():

        result_item = Item(id=key,
                           geometry=s2_items['pre-event'].item.geometry,
                           bbox=s2_items['pre-event'].item.bbox,
                           datetime=s2_items['pre-event'].item.datetime,
                           properties={})

        result_item.add_asset(key='data',
                              asset=Asset(href='./{}.tif'.format(key), 
                              media_type=value['media_type'], 
                              title=value['title']))

        items.append(result_item)

    #collection.add_items(items)

    catalog.add_items(items)

    catalog.describe()

    catalog.normalize_and_save(root_href='./',
                               catalog_type=CatalogType.SELF_CONTAINED)

    
    shutil.move('{}.tif'.format(output_name), 
            os.path.join('./',
                         output_name,
                         '{}.tif'.format(output_name)))
Exemple #15
0
            running_extent = (
                min(running_extent[0], bbox[0]),
                max(running_extent[1], bbox[1]),
                min(running_extent[2], bbox[2]),
                max(running_extent[3], bbox[3]),
            )
            bbox_list = [bbox[0], bbox[1], bbox[2], bbox[3]]

            huc_item = Item(fid, geom, bbox_list, version_dt, {})

            hand_asset = Asset(
                href="{}/{}/{}hand.tif".format(args.root_uri, fid, fid),
                description="HAND raster, buffer removed, final result",
                media_type="image/tiff; application=geotiff",
            )
            huc_item.add_asset(key="hand", asset=hand_asset)

            wbd_asset = Asset(
                href="{}/{}/{}-wbd.geojson".format(args.root_uri, fid, fid),
                description="HUC unit boundary, extracted from USGS wbd",
                media_type="application/geo+json",
            )
            huc_item.add_asset(key="wbd", asset=wbd_asset)

            flows_asset = Asset(
                href="{}/{}/{}-flows.geojson".format(args.root_uri, fid, fid),
                description="Flowline geometry, extracted from NHDPlus V21",
                media_type="application/geo+json",
            )
            huc_item.add_asset(key="flows", asset=flows_asset)
Exemple #16
0
            item_time = datetime.combine(date(year, month, 1), time.min)

            item = Item(
                item_id,
                geometry=mapping(
                    Polygon([
                        [-92.72807246278022, 29.038948834106055],
                        [-88.02592402528022, 29.038948834106055],
                        [-88.02592402528022, 42.55475543734189],
                        [-92.72807246278022, 42.55475543734189],
                        [-92.72807246278022, 29.038948834106055],
                    ])),
                bbox=[
                    29.038948834106055,
                    -92.72807246278022,
                    42.55475543734189,
                    -88.02592402528022,
                ],
                datetime=item_time,
                properties={},
            )
            asset = Asset("s3://{}/{}".format(obj_summary.bucket_name,
                                              obj_summary.key))
            item.add_asset("labels", asset)
            collection.add_item(item)

    # Save Complete Catalog
    root_path = "./data/catalog"
    collection.normalize_and_save(root_path,
                                  catalog_type=CatalogType.SELF_CONTAINED)
    print("Saved STAC Catalog {} to {}...".format(collection.id, root_path))
Exemple #17
0
def to_pystac_item(
    dataset: DatasetDoc,
    stac_item_destination_url: str,
    dataset_location: Optional[str] = None,
    odc_dataset_metadata_url: Optional[str] = None,
    explorer_base_url: Optional[str] = None,
    collection_url: Optional[str] = None,
) -> pystac.Item:
    """
    Convert the given ODC Dataset into a Stac Item document.

    Note: You may want to call `validate_item(doc)` on the outputs to find any
    incomplete properties.

    :param collection_url: URL to the Stac Collection. Either this or an explorer_base_url
                           should be specified for Stac compliance.
    :param stac_item_destination_url: Public 'self' URL where the stac document will be findable.
    :param dataset_location: Use this location instead of picking from dataset.locations
                             (for calculating relative band paths)
    :param odc_dataset_metadata_url: Public URL for the original ODC dataset yaml document
    :param explorer_base_url: An Explorer instance that contains this dataset.
                              Will allow links to things such as the product definition.
    """

    if dataset.geometry is not None:
        geom = Geometry(dataset.geometry, CRS(dataset.crs))
        wgs84_geometry = geom.to_crs(CRS("epsg:4326"), math.inf)

        geometry = wgs84_geometry.json
        bbox = wgs84_geometry.boundingbox
    else:
        geometry = None
        bbox = None

    properties = eo3_to_stac_properties(dataset, title=dataset.label)
    properties.update(_lineage_fields(dataset.lineage))

    dt = properties["datetime"]
    del properties["datetime"]

    # TODO: choose remote if there's multiple locations?
    # Without a dataset location, all paths will be relative.
    dataset_location = dataset_location or (dataset.locations[0]
                                            if dataset.locations else None)

    item = Item(
        id=str(dataset.id),
        datetime=dt,
        properties=properties,
        geometry=geometry,
        bbox=bbox,
        collection=dataset.product.name,
    )

    # Add links
    if stac_item_destination_url:
        item.links.append(
            Link(
                rel="self",
                media_type=MediaType.JSON,
                target=stac_item_destination_url,
            ))
    if odc_dataset_metadata_url:
        item.links.append(
            Link(
                title="ODC Dataset YAML",
                rel="odc_yaml",
                media_type="text/yaml",
                target=odc_dataset_metadata_url,
            ))

    for link in _odc_links(explorer_base_url, dataset, collection_url):
        item.links.append(link)

    EOExtension.ext(item, add_if_missing=True)

    if dataset.geometry:
        proj = ProjectionExtension.ext(item, add_if_missing=True)
        epsg, wkt = _get_projection(dataset)
        if epsg is not None:
            proj.apply(epsg=epsg, **_proj_fields(dataset.grids))
        elif wkt is not None:
            proj.apply(wkt2=wkt, **_proj_fields(dataset.grids))
        else:
            raise STACError(
                "Projection extension requires either epsg or wkt for crs.")

    # To pass validation, only add 'view' extension when we're using it somewhere.
    if any(k.startswith("view:") for k in properties.keys()):
        ViewExtension.ext(item, add_if_missing=True)

    # Add assets that are data
    for name, measurement in dataset.measurements.items():
        if not dataset_location and not measurement.path:
            # No URL to link to. URL is mandatory for Stac validation.
            continue

        asset = Asset(
            href=_uri_resolve(dataset_location, measurement.path),
            media_type=_media_type(Path(measurement.path)),
            title=name,
            roles=["data"],
        )
        eo = EOExtension.ext(asset)

        # TODO: pull out more information about the band
        band = Band.create(name)
        eo.apply(bands=[band])

        if dataset.grids:
            proj_fields = _proj_fields(dataset.grids, measurement.grid)
            if proj_fields is not None:
                proj = ProjectionExtension.ext(asset)
                # Not sure how this handles None for an EPSG code
                proj.apply(
                    shape=proj_fields["shape"],
                    transform=proj_fields["transform"],
                    epsg=epsg,
                )

        item.add_asset(name, asset=asset)

    # Add assets that are accessories
    for name, measurement in dataset.accessories.items():
        if not dataset_location and not measurement.path:
            # No URL to link to. URL is mandatory for Stac validation.
            continue

        asset = Asset(
            href=_uri_resolve(dataset_location, measurement.path),
            media_type=_media_type(Path(measurement.path)),
            title=_asset_title_fields(name),
            roles=_asset_roles_fields(name),
        )

        item.add_asset(name, asset=asset)

    return item
def label_collection_add_items(
    collection,
    root_catalog,
    uri_list,
    links_func,
    label_description,
    label_type,
    label_classes=None,
    label_tasks=None,
    debug=False,
):
    """ Add uri_list tif uris to collection as LabelItems

    root_catalog is the top level node in the STAC Catalog where the chips labeled by these tifs
    can be found. Required to correctly setup Links to the source chips.

    links_func is a method with the following signature:
        def links_func(root_catalog: Catalog,
                       label_item: LabelItem,
                       country: str,
                       event_id: int): [Link]
    This method should construct a list of links that map the label_item to the STAC objects in
    the root_catalog that label_item is derived from. Assumes for now that the asset referenced
    uses the key "labels"

    The label_ arguments will be passed down to each LabelItem in the collection

    """
    if debug:
        uri_list = list(uri_list)[:10]
    for uri in uri_list:
        if not uri.endswith(".tif"):
            continue

        item_id = os.path.basename(uri).split(".")[0]
        country, event_id, *_ = item_id.split("_")

        params = {}
        params["id"] = item_id
        params["collection"] = collection
        params["datetime"] = image_date_for_country("s1", country)
        params["stac_extensions"] = [Extensions.LABEL]
        params["properties"] = {
            "country": country,
            "event_id": event_id,
        }
        params["bbox"] = get_chip_bbox(uri, country, event_id)
        params["geometry"] = box(*params["bbox"]).__geo_interface__

        label_ext_params = {}
        if isinstance(label_classes, list):
            label_ext_params["label_classes"] = label_classes
        else:
            label_ext_params["label_classes"] = []
        label_ext_params["label_description"] = label_description
        if label_tasks is not None:
            label_ext_params["label_tasks"] = label_tasks
        label_ext_params["label_type"] = label_type

        item = Item(**params)
        item.ext.label.apply(**label_ext_params)
        # Add Asset
        asset = Asset(href=uri,
                      title="GeoTiff",
                      media_type="image/tiff; application=geotiff")
        item.add_asset(key="labels", asset=asset)

        item.links = links_func(root_catalog, item, country, event_id)

        collection.add_item(item)
        print("Collection {}: Added STAC Item {}".format(
            collection.id, item.id))
Exemple #19
0
def scombi(channel_inputs, bands, s_expressions, resolution='highest', aoi=None, color=None, profile=None, lut=None, epsg=None):

    target_dir = 'combi'
    
    if not os.path.exists(target_dir):
    
        os.mkdir(target_dir)
        
    items = []
    assets_href = []
    rescaled = []
    
    for index, input_path in enumerate(channel_inputs):
    #for index, input_path in enumerate([red_channel_input, green_channel_input, blue_channel_input]):
    
        if input_path is None:
            
            items.append(None)
            assets_href.append(None)
            continue
            
        item = get_item(input_path) 
        
        logging.info(item)
        
        items.append(item)
        assets_href.append(get_band_asset_href(item, bands[index]))

    # define AOI, if none is supplied, get the minimum bbox 
    if aoi is None:
        aoi = get_mbb([shape(item.geometry) for item in items]).wkt

    min_lon, min_lat, max_lon, max_lat = loads(aoi).bounds

    # analyze get an EPSG code if it hasn't been supplied
    # check if warp is needed
    epsg, epsg_codes = get_epsg(epsg, assets_href)

    # rescale and get the original assets (these are part of the output)
    logging.info('Rescaling and COG for input assets')
    rescaled = []
    
    # get the data
    for index, asset_href in enumerate(assets_href):

        if asset_href is None:
            
            rescaled.append(None)
            
            continue
            
        logging.info('Getting band {} from {}'.format(bands[index], asset_href))
        
        output_name = '{}/{}_{}.tif'.format(target_dir, index+1, bands[index])

        
        if epsg_codes[index] == epsg:

            ds = gdal.Translate(output_name, 
                                asset_href, 
                                outputType=gdal.GDT_Float32,
                                projWin=[min_lon, max_lat, max_lon, min_lat],
                                projWinSRS='EPSG:4326')

        else:

            logging.info('Warp')
            ds = gdal.Warp(output_name, 
                        asset_href, 
                        outputType=gdal.GDT_Float32,
                        outputBounds=[min_lon, min_lat, max_lon, max_lat],
                        outputBoundsSRS='EPSG:4326',
                        dstSRS=epsg) 
        

        ds = None

        del(ds)
        #rescaled.append(ds)
        rescaled.append(output_name)
    
    # build a VRT with the rescaled assets with the selected resolution mode
    logging.info('Build VRT')
    vrt = 'temp.vrt'
    ds = gdal.BuildVRT(vrt,
                       [ds for ds in rescaled if ds],
                       resolution=resolution, 
                       separate=True)

    ds.FlushCache()
    
    output_cell_size = ds.GetGeoTransform()[1]

    logging.info(str(output_cell_size))

    logging.info('Pimp me')

    pimp.me(vrt, 
            f'{target_dir}/combi.tif', 
            bands, 
            s_expressions,
            color, 
            lut)

    ds = None
    del(ds)
    
    # to STAC
    logging.info('STAC')
    cat = Catalog(id='scombidooo',
                  description="Combined RGB composite") 

    # TODO fix datetime
    item = Item(id='combi',
                geometry=mapping(loads(aoi)),
                bbox=list(loads(aoi).bounds),
                datetime=items[0].datetime,
                properties={'bands': bands,
                            's_expressions': s_expressions,
                            'input_items': [_item.id for _item in items],
                            'color': 'N/A' if not color else color,
                            'profile': 'N/A' if not profile else profile}) 

    item.common_metadata.set_gsd(output_cell_size)

    eo_item = extensions.eo.EOItemExt(item)

    for index, asset_href in enumerate(assets_href):
        if asset_href is None:
            continue
        _asset =  get_band_asset(items[index],
                                 bands[index]) 
      
        _asset.href = './{}_{}.tif'.format(index+1, bands[index])

        item.add_asset('{}_{}'.format(index+1, bands[index]), _asset)

        
    # add the result.tif Asset
    item.add_asset(key='rgb',
                   asset=Asset(href='./combi.tif',
                               media_type=MediaType.COG))
        
    cat.add_items([item])
    
    cat.normalize_and_save(root_href='./',
                           catalog_type=CatalogType.SELF_CONTAINED)
     
    logging.info('Done!')

    return(cat.get_self_href())
            )
            text_asset = Asset(
                href="{}-usfimr.wkt".format(fid),
                description="well known text representation",
                media_type="application/wkt",
            )
            json_asset = Asset(
                href="{}-usfimr.geojson".format(fid),
                description="geojson representation",
                media_type="application/geo+json",
            )
            serializable_convex_hull = mapping(shapely_geom.convex_hull)
            item = Item(fid, serializable_convex_hull, bbox_list, start_dt,
                        deepcopy(props))
            text_asset.set_owner(item)
            item.add_asset(key="wkt", asset=text_asset)
            binary_asset.set_owner(item)
            item.add_asset(key="wkb", asset=binary_asset)
            json_asset.set_owner(item)
            item.add_asset(key="geojson", asset=json_asset)
            items.append(item)

            os.makedirs("{}/{}".format(root_path, fid), exist_ok=True)

            with open("{}/{}/{}-usfimr.wkt".format(root_path, fid, fid),
                      "w") as wkt_file:
                wkt_file.write(shapely_geom.wkt)

            with open("{}/{}/{}-usfimr.wkb".format(root_path, fid, fid),
                      "wb") as wkb_file:
                wkb_file.write(shapely_geom.wkb)