示例#1
0
def desc_coverages(args):
    # Note: Only WCS v1.0.0 is fully supported at this stage, so no version negotiation is necessary
    # Extract layer metadata from Datacube.
    platforms = get_layers(refresh=True)

    coverages = args.get("coverage")
    products = []
    if coverages:
        coverages = coverages.split(",")
        for c in coverages:
            p = platforms.product_index.get(c)
            if p:
                products.append(p)
            else:
                raise WCS1Exception("Invalid coverage: %s" % c,
                                    WCS1Exception.COVERAGE_NOT_DEFINED,
                                    locator="Coverage parameter")
    else:
        for plat in platforms:
            for p in plat.products:
                products.append(p)

    return (render_template("wcs_desc_coverage.xml",
                            service=get_service_cfg(),
                            products=products), 200,
            resp_headers({
                "Content-Type": "application/xml",
                "Cache-Control": "max-age=10"
            }))
示例#2
0
def update_all_ranges(dc):
    i = 0
    u = 0
    p = 0
    si = 0
    su = 0
    sp = 0
    mi = 0
    mu = 0
    mp = 0

    multiproducts = set()

    for layer in get_layers():
        for prod in layer.products:
            if prod.multi_product:
                multiproducts.add(prod)
            else:
                stats = update_single_range(dc, prod)
                p += stats[0]
                u += stats[1]
                i += stats[2]
                sp += stats[3]
                su += stats[4]
                si += stats[5]

    for mprod in multiproducts:
        stats = update_multi_range(dc, mprod, follow_dependencies=False)
        mp += stats[0]
        mu += stats[1]
        mi += stats[2]

    return p, u, i, sp, su, si, mp, mu, mi
示例#3
0
def get_capabilities(args):
    # TODO: Handle updatesequence request parameter for cache consistency.
    # Note: Only WMS v1.0.0 exists at this stage, so no version negotiation is necessary
    # Extract layer metadata from Datacube.
    platforms = get_layers(refresh=True)
    service_cfg = get_service_cfg()
    url = args.get('Host', args['url_root'])
    base_url = get_service_base_url(service_cfg.allowed_urls, url)
    section = args.get("section")
    if section:
        section = section.lower()
    show_service_id = False
    show_service_provider = False
    show_ops_metadata = False
    show_contents = False
    show_themes = False
    if section is None:
        show_service_id = True
        show_service_provider = True
        show_ops_metadata = True
        show_contents = True
        show_themes = True
    else:
        sections = section.split(",")
        for s in sections:
            if s == "all":
                show_service_id = True
                show_service_provider = True
                show_ops_metadata = True
                show_contents = True
                show_themes = True
            elif s == "serviceidentification":
                show_service_id = True
            elif s == "serviceprovider":
                show_service_provider = True
            elif s == "operationsmetadata":
                show_ops_metadata = True
            elif s == "contents":
                show_contents = True
            elif s == "themes":
                show_themes = True
            else:
                raise WMTSException("Invalid section: %s" % section,
                                    WMTSException.INVALID_PARAMETER_VALUE,
                                    locator="Section parameter")
    return (render_template("wmts_capabilities.xml",
                            service=service_cfg,
                            platforms=platforms,
                            base_url=base_url,
                            show_service_id=show_service_id,
                            show_service_provider=show_service_provider,
                            show_ops_metadata=show_ops_metadata,
                            show_contents=show_contents,
                            show_themes=show_themes,
                            webmerc_ss=WebMercScaleSet), 200,
            resp_headers({
                "Content-Type": "application/xml",
                "Cache-Control": "no-cache,max-age=0"
            }))
示例#4
0
def test_get_layers():
    layers = get_layers()

    assert layers.platforms
    for p in layers:
        assert p.styles
        assert p.products
        for prd in p.products:
            assert layers.product_index[prd.name] == prd
            assert prd.title
示例#5
0
def get_capabilities(args):
    if args.get("service") != "WMS":
        raise WMSException("Invalid service", locator="Service parameter")
    # TODO: Handle updatesequence request parameter for cache consistency.
    # Note: Only WMS v1.3.0 is fully supported at this stage, so no version negotiation is necessary
    # Extract layer metadata from Datacube.
    platforms = get_layers()
    return render_template("capabilities.xml",
                           service=service_cfg,
                           platforms=platforms), 200, resp_headers(
                               {"Content-Type": "application/xml"})
示例#6
0
def legend(layer, style):
    platforms = get_layers()
    product = platforms.product_index.get(layer)
    if not product:
        return ("Unknown Layer", 404,
                resp_headers({"Content-Type": "text/plain"}))
    img = create_legend_for_style(product, style)
    if not img:
        return ("Unknown Style", 404,
                resp_headers({"Content-Type": "text/plain"}))
    return img
示例#7
0
def get_product_from_arg(args, argname="layers"):
    layers = args.get(argname, "").split(",")
    if len(layers) != 1:
        raise WMSException("Multi-layer requests not supported")
    layer = layers[0]
    platforms = get_layers()
    product = platforms.product_index.get(layer)
    if not product:
        raise WMSException("Layer %s is not defined" % layer,
                           WMSException.LAYER_NOT_DEFINED,
                           locator="Layer parameter")
    return product
示例#8
0
def update_range(dc, product, multi=False, follow_dependencies=True):
    if multi:
        product = get_layers().product_index.get(product)
    else:
        product = dc.index.products.get_by_name(product)

    if product is None:
        raise Exception("Requested product not found.")

    if multi:
        return update_multi_range(dc, product, follow_dependencies=follow_dependencies)
    else:
        return update_single_range(dc, product)
示例#9
0
def get_capabilities(args):
    # TODO: Handle updatesequence request parameter for cache consistency.
    # Note: Only WMS v1.3.0 is fully supported at this stage, so no version negotiation is necessary
    # Extract layer metadata from Datacube.
    platforms = get_layers(refresh=True)
    return render_template("wms_capabilities.xml",
                           service=get_service_cfg(),
                           platforms=platforms), 200, resp_headers({
                               "Content-Type":
                               "application/xml",
                               "Cache-Control":
                               "no-cache,max-age=0"
                           })
示例#10
0
def add_all(dc):
    multi_products = set()
    for layer in get_layers():
        for product_cfg in layer.products:
            product_name = product_cfg.product_name
            if product_cfg.multi_product:
                multi_products.add(product_cfg)
            else:
                print("Adding range for:", product_name)
                add_product_range(dc, product_name)

    for p in multi_products:
        print("Adding multiproduct range for:", p.name)
        add_multiproduct_range(dc, p, follow_dependencies=False)
示例#11
0
def add_multiproduct_range(dc, product, follow_dependencies=True):
    if isinstance(product, str):
        product = get_layers().product_index.get(product)

    assert product is not None

    if follow_dependencies:
        for product_name in product.product_names:
            dc_prod = dc.index.products.get_by_name(product_name)
            add_product_range(dc, dc_prod)
            if not check_datasets_exist(dc, dc_prod):
                print("Could not find any datasets for: ", product_name)

    # Actually merge and store!
    create_multiprod_range_entry(dc, product, get_crses())
示例#12
0
def get_capabilities(args):
    # TODO: Handle updatesequence request parameter for cache consistency.
    # Note: Only WMS v1.3.0 is fully supported at this stage, so no version negotiation is necessary
    # Extract layer metadata from Datacube.
    platforms = get_layers(refresh=True)
    service_cfg = get_service_cfg()
    url = args.get('Host', args['url_root'])
    base_url = get_service_base_url(service_cfg.allowed_urls, url)
    return (render_template("wms_capabilities.xml",
                            service=service_cfg,
                            platforms=platforms,
                            base_url=base_url), 200,
            resp_headers({
                "Content-Type": "application/xml",
                "Cache-Control": "max-age=10"
            }))
示例#13
0
def get_capabilities(args):
    # TODO: Handle updatesequence request parameter for cache consistency.
    # Note: Only WCS v1.0.0 is fully supported at this stage, so no version negotiation is necessary
    section = args.get("section")
    if section:
        section = section.lower()
    show_service = False
    show_capability = False
    show_content_metadata = False
    if section is None or section == "/":
        show_service = True
        show_capability = True
        show_content_metadata = True
    elif section == "/wcs_capabilities/service":
        show_service = True
    elif section == "/wcs_capabilities/capability":
        show_capability = True
    elif section == "/wcs_capabilities/contentmetadata":
        show_content_metadata = True
    else:
        raise WCS1Exception("Invalid section: %s" % section,
                            WCS1Exception.INVALID_PARAMETER_VALUE,
                            locator="Section parameter")

    # Extract layer metadata from Datacube.
    platforms = get_layers(refresh=True)
    service_cfg = get_service_cfg()
    url = args.get('Host', args['url_root'])
    base_url = get_service_base_url(service_cfg.allowed_urls, url)
    return (
        render_template("wcs_capabilities.xml",
                        show_service=show_service,
                        show_capability=show_capability,
                        show_content_metadata=show_content_metadata,
                        service=service_cfg,
                        platforms=platforms,
                        base_url=base_url),
        200,
        resp_headers({
            "Content-Type": "application/xml",
            "Cache-Control": "no-cache, max-age=0"
        }))
示例#14
0
def get_coverage(args):
    decoder = WCS20GetCoverageKVPDecoder(args)

    try:
        coverage_id = decoder.coverage_id
    except KeyError:
        raise WCS2Exception("Missing coverageid parameter", locator="coverageid")

    svc_cfg = get_service_cfg(refresh=True)
    layers = get_layers(refresh=True)

    product = layers.product_index.get(coverage_id)

    if not product:
        raise WCS2Exception("Invalid coverage: %s" % coverage_id,
                            WCS2Exception.COVERAGE_NOT_DEFINED,
                            locator="COVERAGE parameter")

    if decoder.format:
        if decoder.format not in svc_cfg.wcs_formats:
            raise WCS2Exception("Unsupported format: %s" % decoder.format,
                                WCS2Exception.INVALID_PARAMETER_VALUE,
                                locator="FORMAT parameter")
    elif not svc_cfg.native_wcs_format:
        raise WCS2Exception("Missing parameter format 'format'",
                            WCS2Exception.MISSING_PARAMETER_VALUE,
                            locator="FORMAT parameter")

    fmt_cfg = svc_cfg.wcs_formats[decoder.format or svc_cfg.native_wcs_format]

    

    return (
        '',
        200,
        resp_headers({
            "Content-Type": "application/xml",
            "Cache-Control": "no-cache, max-age=0"
        })
    )
示例#15
0
def desc_coverages(args):
    try:
        coverage_ids = [s.strip() for s in args['coverageid'].split(',')]
    except KeyError:
        raise WCS2Exception("Missing coverageid parameter", locator="coverageid")

    svc_cfg = get_service_cfg(refresh=True)
    layers = get_layers(refresh=True)

    products = []
    for coverage_id in coverage_ids:
        product = layers.product_index.get(coverage_id)
        if product:
            products.append(product)
        else:
            raise WCS2Exception("Invalid coverage: %s" % coverage_id,
                                WCS2Exception.COVERAGE_NOT_DEFINED,
                                locator="Coverage parameter")

    # TODO: make a coverge object from each of the 'products'

    coverages = [
        get_coverage_object(svc_cfg, product)
        for product in products
    ]

    encoder = WCS21XMLEncoder()
    return (
        encoder.serialize(
            encoder.encode_coverage_descriptions(coverages)
        ),
        200,
        resp_headers({
            "Content-Type": "application/xml",
            "Cache-Control": "no-cache, max-age=0"
        })
    )
示例#16
0
    def __init__(self, args):
        self.args = args
        layers = get_layers()
        svc_cfg = get_service_cfg()

        # Argument: Coverage (required)
        if "coverage" not in args:
            raise WCS1Exception("No coverage specified",
                                WCS1Exception.MISSING_PARAMETER_VALUE,
                                locator="COVERAGE parameter")
        self.product_name = args["coverage"]
        self.product = layers.product_index.get(self.product_name)
        if not self.product:
            raise WCS1Exception("Invalid coverage: %s" % self.product_name,
                                WCS1Exception.COVERAGE_NOT_DEFINED,
                                locator="COVERAGE parameter")

        # Argument: FORMAT (required)
        if "format" not in args:
            raise WCS1Exception("No FORMAT parameter supplied",
                                WCS1Exception.MISSING_PARAMETER_VALUE,
                                locator="FORMAT parameter")
        if args["format"] not in svc_cfg.wcs_formats:
            raise WCS1Exception("Unsupported format: %s" % args["format"],
                                WCS1Exception.INVALID_PARAMETER_VALUE,
                                locator="FORMAT parameter")
        self.format = svc_cfg.wcs_formats[args["format"]]

        # Argument: (request) CRS (required)
        if "crs" not in args:
            raise WCS1Exception("No request CRS specified",
                                WCS1Exception.MISSING_PARAMETER_VALUE,
                                locator="CRS parameter")
        self.request_crsid = args["crs"]
        if self.request_crsid not in svc_cfg.published_CRSs:
            raise WCS1Exception("%s is not a supported CRS" %
                                self.request_crsid,
                                WCS1Exception.INVALID_PARAMETER_VALUE,
                                locator="CRS parameter")
        self.request_crs = geometry.CRS(self.request_crsid)

        # Argument: response_crs (optional)
        if "response_crs" in args:
            self.response_crsid = args["response_crs"]
            if self.response_crsid not in svc_cfg.published_CRSs:
                raise WCS1Exception("%s is not a supported CRS" %
                                    self.request_crsid,
                                    WCS1Exception.INVALID_PARAMETER_VALUE,
                                    locator="RESPONSE_CRS parameter")
            self.response_crs = geometry.CRS(self.response_crsid)
        else:
            self.response_crsid = self.request_crsid
            self.response_crs = self.request_crs

        # Arguments: One of BBOX or TIME is required
        #if "bbox" not in args and "time" not in args:
        #    raise WCS1Exception("At least one of BBOX or TIME parameters must be supplied",
        #                        WCS1Exception.MISSING_PARAMETER_VALUE,
        #                        locator="BBOX or TIME parameter"
        #                        )

        # Argument: BBOX (technically not required if TIME supplied, but
        #       it's not clear to me what that would mean.)
        # For WCS 1.0.0 all bboxes will be specified as minx, miny, maxx, maxy
        if "bbox" not in args:
            raise WCS1Exception("No BBOX parameter supplied",
                                WCS1Exception.MISSING_PARAMETER_VALUE,
                                locator="BBOX or TIME parameter")
        try:
            self.minx, self.miny, self.maxx, self.maxy = map(
                float, args['bbox'].split(','))
        except:
            raise WCS1Exception("Invalid BBOX parameter",
                                WCS1Exception.INVALID_PARAMETER_VALUE,
                                locator="BBOX parameter")

        # Argument: TIME
        if self.product.wcs_sole_time:
            self.times = [parse(self.product.wcs_sole_time).date()]
        elif "time" not in args:
            #      CEOS treats no supplied time argument as all time.
            # I'm really not sure what the right thing to do is, but QGIS wants us to do SOMETHING
            self.times = [self.product.ranges["times"][-1]]
        else:
            # TODO: the min/max/res format option?
            # It's a bit underspeced. I'm not sure what the "res" would look like.
            times = args["time"].split(",")
            self.times = []
            if times == "now":
                pass
            else:
                for t in times:
                    try:
                        time = parse(t).date()
                        if time not in self.product.ranges["time_set"]:
                            raise WCS1Exception(
                                "Time value '%s' not a valid date for coverage %s"
                                % (t, self.product_name),
                                WCS1Exception.INVALID_PARAMETER_VALUE,
                                locator="TIME parameter")
                        self.times.append(time)
                    except ValueError:
                        raise WCS1Exception(
                            "Time value '%s' not a valid ISO-8601 date" % t,
                            WCS1Exception.INVALID_PARAMETER_VALUE,
                            locator="TIME parameter")
                self.times.sort()

            if len(times) == 0:
                raise WCS1Exception("No valid ISO-8601 dates",
                                    WCS1Exception.INVALID_PARAMETER_VALUE,
                                    locator="TIME parameter")
            elif len(times) > 1 and not self.format["multi-time"]:
                raise WCS1Exception(
                    "Cannot select more than one time slice with the %s format"
                    % self.format["name"],
                    WCS1Exception.INVALID_PARAMETER_VALUE,
                    locator="TIME and FORMAT parameters")

        # Range constraint parameter: MEASUREMENTS
        # No default is set in the DescribeCoverage, so it is required
        # But QGIS wants us to work without one, so take default from config
        if "measurements" in args:
            bands = args["measurements"]
            self.bands = []
            for b in bands.split(","):
                try:
                    self.bands.append(self.product.band_idx.band(b))
                except ProductLayerException:
                    raise WCS1Exception("Invalid measurement '%s'" % b,
                                        WCS1Exception.INVALID_PARAMETER_VALUE,
                                        locator="MEASUREMENTS parameter")
            if not bands:
                raise WCS1Exception("No measurements supplied",
                                    WCS1Exception.INVALID_PARAMETER_VALUE,
                                    locator="MEASUREMENTS parameter")
        elif "styles" in args and args["styles"]:
            # Use style bands.
            # Non-standard protocol extension.
            #
            # As we have correlated WCS and WMS service implementations,
            # we can accept a style from WMS, and return the bands used for it.
            styles = args["styles"].split(",")
            if len(styles) != 1:
                raise WCS1Exception("Multiple style parameters not supported")
            style = self.product.style_index.get(styles[0])
            if style:
                self.bands = style.needed_bands
            else:
                self.bands = self.product.wcs_default_bands
        else:
            self.bands = self.product.wcs_default_bands

        # Argument: EXCEPTIONS (optional - defaults to XML)
        if "exceptions" in args and args[
                "exceptions"] != "application/vnd.ogc.se_xml":
            raise WCS1Exception("Unsupported exception format: " %
                                args["exceptions"],
                                WCS1Exception.INVALID_PARAMETER_VALUE,
                                locator="EXCEPTIONS parameter")

        # Argument: INTERPOLATION (optional only nearest-neighbour currently supported.)
        #      If 'none' is supported in future, validation of width/height/res will need to change.
        if "interpolation" in args and args[
                "interpolation"] != "nearest neighbor":
            raise WCS1Exception("Unsupported interpolation method: " %
                                args["interpolation"],
                                WCS1Exception.INVALID_PARAMETER_VALUE,
                                locator="INTERPOLATION parameter")

        if "width" in args:
            if "height" not in args:
                raise WCS1Exception(
                    "WIDTH parameter supplied without HEIGHT parameter",
                    WCS1Exception.MISSING_PARAMETER_VALUE,
                    locator="WIDTH/HEIGHT parameters")
            if "resx" in args or "resy" in args:
                raise WCS1Exception(
                    "Specify WIDTH/HEIGHT parameters OR RESX/RESY parameters - not both",
                    WCS1Exception.MISSING_PARAMETER_VALUE,
                    locator="RESX/RESY/WIDTH/HEIGHT parameters")
            try:
                self.height = int(args["height"])
                if self.height < 1:
                    raise ValueError()
            except ValueError:
                raise WCS1Exception(
                    "HEIGHT parameter must be a positive integer",
                    WCS1Exception.INVALID_PARAMETER_VALUE,
                    locator="HEIGHT parameter")
            try:
                self.width = int(args["width"])
                if self.width < 1:
                    raise ValueError()
            except ValueError:
                raise WCS1Exception(
                    "WIDTH parameter must be a positive integer",
                    WCS1Exception.INVALID_PARAMETER_VALUE,
                    locator="WIDTH parameter")
            self.resx = (self.maxx - self.minx) / self.width
            self.resy = (self.maxy - self.miny) / self.height
        elif "resx" in args:
            if "resy" not in args:
                raise WCS1Exception(
                    "RESX parameter supplied without RESY parameter",
                    WCS1Exception.MISSING_PARAMETER_VALUE,
                    locator="RESX/RESY parameters")
            if "height" in args:
                raise WCS1Exception(
                    "Specify WIDTH/HEIGHT parameters OR RESX/RESY parameters - not both",
                    WCS1Exception.MISSING_PARAMETER_VALUE,
                    locator="RESX/RESY/WIDTH/HEIGHT parameters")
            try:
                self.resx = float(args["resx"])
                if self.resx <= 0.0:
                    raise ValueError(0)
            except ValueError:
                raise WCS1Exception("RESX parameter must be a positive number",
                                    WCS1Exception.INVALID_PARAMETER_VALUE,
                                    locator="RESX parameter")
            try:
                self.resy = float(args["resy"])
                if self.resy <= 0.0:
                    raise ValueError(0)
            except ValueError:
                raise WCS1Exception("RESY parameter must be a positive number",
                                    WCS1Exception.INVALID_PARAMETER_VALUE,
                                    locator="RESY parameter")
            self.width = (self.maxx - self.minx) / self.resx
            self.height = (self.maxy - self.miny) / self.resy
            self.width = int(self.width + 0.5)
            self.height = int(self.height + 0.5)
        elif "height" in args:
            raise WCS1Exception(
                "HEIGHT parameter supplied without WIDTH parameter",
                WCS1Exception.MISSING_PARAMETER_VALUE,
                locator="WIDTH/HEIGHT parameters")
        elif "resy" in args:
            raise WCS1Exception(
                "RESY parameter supplied without RESX parameter",
                WCS1Exception.MISSING_PARAMETER_VALUE,
                locator="RESX/RESY parameters")
        else:
            raise WCS1Exception(
                "You must specify either the WIDTH/HEIGHT parameters or RESX/RESY",
                WCS1Exception.MISSING_PARAMETER_VALUE,
                locator="RESX/RESY/WIDTH/HEIGHT parameters")

        self.extent = geometry.polygon([(self.minx, self.miny),
                                        (self.minx, self.maxy),
                                        (self.maxx, self.maxy),
                                        (self.maxx, self.miny),
                                        (self.minx, self.miny)],
                                       self.request_crs)

        xscale = (self.maxx - self.minx) / self.width
        yscale = (self.miny - self.maxy) / self.height
        trans_aff = Affine.translation(self.minx, self.maxy)
        scale_aff = Affine.scale(xscale, yscale)
        self.affine = trans_aff * scale_aff
        self.geobox = geometry.GeoBox(self.width, self.height, self.affine,
                                      self.request_crs)