示例#1
0
def _make_band_dict(prod_cfg, pixel_dataset, band_list):
    band_dict = {}
    for band in band_list:
        try:
            band_lbl = prod_cfg.band_idx.band_label(band)
            ret_val = band_val = pixel_dataset[band].item()
            if band_val == pixel_dataset[band].nodata or numpy.isnan(band_val):
                band_dict[band_lbl] = "n/a"
            else:
                if 'flags_definition' in pixel_dataset[band].attrs:
                    flag_def = pixel_dataset[band].attrs['flags_definition']
                    # HACK: Work around bands with floating point values
                    try:
                        flag_dict = mask_to_dict(flag_def, band_val)
                    except TypeError as te:
                        logging.warning('Working around for float bands')
                        flag_dict = mask_to_dict(flag_def, int(band_val))
                    try:
                        ret_val = [
                            flag_def[flag]['description']
                            for flag, val in flag_dict.items() if val
                        ]
                    except KeyError:
                        # Weirdly formatted flag definition.  Hacky workaround for USGS data in DEAfrica demo.
                        ret_val = [
                            val for flag, val in flag_dict.items() if val
                        ]
                band_dict[band_lbl] = ret_val
        except ConfigException:
            pass
    return band_dict
示例#2
0
def test_simple_mask_to_dict():
    simple_var = SimpleVariableWithFlagsDef()
    bits_def = simple_var.flags_definition

    contiguous_true = mask_to_dict(bits_def, 256)
    assert contiguous_true['contiguous']

    test_dict = mask_to_dict(bits_def, 768)
    assert test_dict['contiguous']
    assert test_dict['land_sea'] == 'land'

    test_dict = mask_to_dict(bits_def, 16383)
    assert test_dict['ga_good_pixel']
def test_simple_mask_to_dict():
    simple_var = SimpleVariableWithFlagsDef()
    bits_def = simple_var.flags_definition

    contiguous_true = mask_to_dict(bits_def, 256)
    assert contiguous_true['contiguous']

    test_dict = mask_to_dict(bits_def, 768)
    assert test_dict['contiguous']
    assert test_dict['land_sea'] == 'land'

    test_dict = mask_to_dict(bits_def, 16383)
    assert test_dict['ga_good_pixel']
示例#4
0
def _make_band_dict(prod_cfg, pixel_dataset, band_list):
    band_dict = {}
    for band in band_list:
        try:
            band_lbl = prod_cfg.band_idx.band_label(band)
            ret_val = band_val = pixel_dataset[band].item()
            if band_val == pixel_dataset[band].nodata or numpy.isnan(band_val):
                band_dict[band_lbl] = "n/a"
            else:
                if 'flags_definition' in pixel_dataset[band].attrs:
                    flag_def = pixel_dataset[band].attrs['flags_definition']
                    flag_dict = mask_to_dict(flag_def, band_val)
                    try:
                        ret_val = [
                            flag_def[flag]['description']
                            for flag, val in flag_dict.items() if val
                        ]
                    except KeyError:
                        # Weirdly formatted flag definition.  Hacky workaround for USGS data in DEAfrica demo.
                        ret_val = [
                            val for flag, val in flag_dict.items() if val
                        ]
                band_dict[band_lbl] = ret_val
        except ProductLayerException:
            pass
    return band_dict
示例#5
0
def test_simple_mask_to_dict(bits_def):
    # All 0. Contiguous should be False, Saturated bits should be true
    test_dict = mask_to_dict(bits_def, 0)
    assert not test_dict['contiguous']
    assert test_dict['blue_saturated']

    # Only contiguous (bit 8) set
    test_dict = mask_to_dict(bits_def, 256)
    assert test_dict['contiguous']
    assert test_dict['blue_saturated']
    assert test_dict['land_sea'] == 'sea'

    # Contiguous and land_sea bits set to 1. (bits 7 and 8)
    test_dict = mask_to_dict(bits_def, 768)
    assert test_dict['contiguous']
    assert test_dict['land_sea'] == 'land'
    assert test_dict['blue_saturated']

    # All GA PQ bits set to 1
    test_dict = mask_to_dict(bits_def, 16383)
    assert test_dict['ga_good_pixel']
    assert test_dict['contiguous']
    assert test_dict['land_sea'] == 'land'
    assert not test_dict['blue_saturated']
示例#6
0
def _make_band_dict(prod_cfg, pixel_dataset, band_list):
    band_dict = {}
    for band in band_list:
        try:
            band_lbl = prod_cfg.band_idx.band_label(band)
            ret_val = band_val = pixel_dataset[band].item()
            if band_val == pixel_dataset[band].nodata or numpy.isnan(band_val):
                band_dict[band_lbl] = "n/a"
            else:
                if 'flags_definition' in pixel_dataset[band].attrs:
                    flag_def = pixel_dataset[band].attrs['flags_definition']
                    flag_dict = mask_to_dict(flag_def, band_val)
                    ret_val = [
                        flag_def[flag]['description']
                        for flag, val in flag_dict.items() if val
                    ]
                band_dict[band_lbl] = ret_val
        except ProductLayerException:
            pass
    return band_dict
示例#7
0
def feature_info(args):
    # pylint: disable=too-many-nested-blocks, too-many-branches, too-many-statements, too-many-locals
    # Parse GET parameters
    params = GetFeatureInfoParameters(args)

    # Prepare to extract feature info
    stacker = DataStacker(params.product, params.geobox, params.time)
    feature_json = {}

    # --- Begin code section requiring datacube.
    service_cfg = get_service_cfg()
    dc = get_cube()
    try:
        geo_point = img_coords_to_geopoint(params.geobox, params.i, params.j)
        datasets = stacker.datasets(dc.index, all_time=True, point=geo_point)
        pq_datasets = stacker.datasets(dc.index,
                                       mask=True,
                                       all_time=False,
                                       point=geo_point)

        h_coord = service_cfg.published_CRSs[params.crsid]["horizontal_coord"]
        v_coord = service_cfg.published_CRSs[params.crsid]["vertical_coord"]
        isel_kwargs = {h_coord: [params.i], v_coord: [params.j]}
        if not datasets:
            pass
        else:
            available_dates = set()
            drill = {}
            for d in datasets:
                idx_date = (d.center_time +
                            timedelta(hours=params.product.time_zone)).date()
                available_dates.add(idx_date)
                pixel_ds = None
                if idx_date == params.time and "lon" not in feature_json:
                    data = stacker.data([d], skip_corrections=True)

                    # Use i,j image coordinates to extract data pixel from dataset, and
                    # convert to lat/long geographic coordinates
                    if service_cfg.published_CRSs[params.crsid]["geographic"]:
                        # Geographic coordinate systems (e.g. EPSG:4326/WGS-84) are already in lat/long
                        feature_json["lat"] = data.latitude[params.j].item()
                        feature_json["lon"] = data.longitude[params.i].item()
                        pixel_ds = data.isel(**isel_kwargs)
                    else:
                        # Non-geographic coordinate systems need to be projected onto a geographic
                        # coordinate system.  Why not use EPSG:4326?
                        # Extract coordinates in CRS
                        data_x = getattr(data, h_coord)
                        data_y = getattr(data, v_coord)

                        x = data_x[params.i].item()
                        y = data_y[params.j].item()
                        pt = geometry.point(x, y, params.crs)

                        # Project to EPSG:4326
                        crs_geo = geometry.CRS("EPSG:4326")
                        ptg = pt.to_crs(crs_geo)

                        # Capture lat/long coordinates
                        feature_json["lon"], feature_json["lat"] = ptg.coords[
                            0]

                    # Extract data pixel
                    pixel_ds = data.isel(**isel_kwargs)

                    # Get accurate timestamp from dataset
                    feature_json["time"] = d.center_time.strftime(
                        "%Y-%m-%d %H:%M:%S UTC")

                    feature_json["bands"] = {}
                    # Collect raw band values for pixel
                    for band in stacker.needed_bands():
                        ret_val = band_val = pixel_ds[band].item()
                        if band_val == pixel_ds[band].nodata:
                            feature_json["bands"][band] = "n/a"
                        else:
                            if hasattr(pixel_ds[band], 'flags_definition'):
                                flag_def = pixel_ds[band].flags_definition
                                flag_dict = mask_to_dict(flag_def, band_val)
                                ret_val = [
                                    flag_def[k]['description']
                                    for k in filter(flag_dict.get, flag_dict)
                                ]
                            feature_json["bands"][band] = ret_val

                    for k, v in filter(
                            lambda kv: hasattr(kv[1], 'index_function'),
                            params.product.style_index.items()):
                        if v.index_function is None:
                            continue

                        vals_nodata = [
                            pixel_ds[b] == pixel_ds[b].nodata
                            for b in v.needed_bands
                        ]
                        if any(vals_nodata):
                            continue

                        value = v.index_function(pixel_ds).item()
                        try:
                            feature_json["band_derived"][k] = value
                        except KeyError:
                            feature_json["band_derived"] = {}
                            feature_json["band_derived"][k] = value

                if params.product.band_drill:
                    if pixel_ds is None:
                        data = stacker.data([d], skip_corrections=True)
                        pixel_ds = data.isel(**isel_kwargs)
                    drill_section = {}
                    for band in params.product.band_drill:
                        band_val = pixel_ds[band].item()
                        if band_val == pixel_ds[band].nodata:
                            drill_section[band] = "n/a"
                        else:
                            drill_section[band] = pixel_ds[band].item()
                    drill[idx_date.strftime("%Y-%m-%d")] = drill_section
            if drill:
                feature_json["time_drill"] = drill
                feature_json["datasets_read"] = len(datasets)
            my_flags = 0
            pqdi = -1
            for pqd in pq_datasets:
                pqdi += 1
                idx_date = (pqd.center_time +
                            timedelta(hours=params.product.time_zone)).date()
                if idx_date == params.time:
                    pq_data = stacker.data([pqd], mask=True)
                    pq_pixel_ds = pq_data.isel(**isel_kwargs)
                    # PQ flags
                    m = params.product.pq_product.measurements[
                        params.product.pq_band]
                    flags = pq_pixel_ds[params.product.pq_band].item()
                    if not flags & ~params.product.info_mask:
                        my_flags = my_flags | flags
                    else:
                        continue
                    feature_json["flags"] = {}
                    for mk, mv in m["flags_definition"].items():
                        if mk in params.product.ignore_flags_info:
                            continue
                        bits = mv["bits"]
                        values = mv["values"]
                        if not isinstance(bits, int):
                            continue
                        flag = 1 << bits
                        if my_flags & flag:
                            val = values['1']
                        else:
                            val = values['0']
                        feature_json["flags"][mk] = val

            lads = list(available_dates)
            lads.sort()
            feature_json["data_available_for_dates"] = [
                d.strftime("%Y-%m-%d") for d in lads
            ]
            feature_json["data_links"] = sorted(get_s3_browser_uris(datasets))
        release_cube(dc)
    except Exception as e:
        release_cube(dc)
        raise e
    # --- End code section requiring datacube.

    result = {
        "type": "FeatureCollection",
        "features": [{
            "type": "Feature",
            "properties": feature_json
        }]
    }
    return json.dumps(result), 200, resp_headers(
        {"Content-Type": "application/json"})