コード例 #1
0
class CoverageDescriptionMapServerRenderer(BaseRenderer):
    """ A coverage description renderer implementation using mapserver.
    """

    versions = (Version(1, 1), Version(1, 0))

    def supports(self, params):
        return (
            params.version in self.versions and
            all(
                not coverage.grid.is_referenceable
                for coverage in params.coverages
            )
        )

    def render(self, params):
        map_ = self.create_map()

        use_name = (params.version == Version(1, 0))

        for coverage in params.coverages:

            # ReferenceableDatasets are not supported in WCS < 2.0
            if coverage.grid.is_referenceable:
                raise NoSuchCoverageException((coverage.identifier,))

            data_locations = self.arraydata_locations_for_coverage(coverage)
            native_format = self.get_native_format(coverage, data_locations)
            layer = self.layer_for_coverage(
                coverage, native_format, params.version
            )
            map_.insertLayer(layer)

        for outputformat in self.get_all_outputformats(not use_name):
            map_.appendOutputFormat(outputformat)

        request = ms.create_request(params)
        raw_result = ms.dispatch(map_, request)
        
        result = result_set_from_raw_data(raw_result)
        # load XML using lxml
        # find and exclude <metadataLink> nodes if present
        # re-encode

        xml_result = etree.fromstring(result[0].data)

        for elem in xml_result.xpath('//*[local-name() = "metadataLink"]'):
            elem.getparent().remove(elem)

        xml_result_data =  etree.tostring(xml_result, pretty_print=True, encoding='UTF-8', xml_declaration=True)
        
        result[0] = ResultBuffer(xml_result_data, result[0].content_type)
        
        return result
コード例 #2
0
class NativeWCS20CapabilitiesRenderer(Component):
    implements(WCSCapabilitiesRendererInterface)

    versions = (Version(2, 0), )

    def supports(self, params):
        if params.version not in self.versions:
            return False

        if params.accept_formats and "text/xml" not in params.accept_formats:
            return False

        # TODO: accept_languages?
        return True

    def render(self, params):
        encoder = WCS20CapabilitiesXMLEncoder()
        return [
            ResultBuffer(
                encoder.serialize(encoder.encode_capabilities(
                    params.sections or ("all"), None, params.coverages,
                    params.dataset_series, params.http_request),
                                  pretty_print=settings.DEBUG),
                encoder.content_type)
        ]
コード例 #3
0
class CoverageDescriptionMapServerRenderer(BaseRenderer):
    """ A coverage description renderer implementation using mapserver.
    """

    implements(WCSCoverageDescriptionRendererInterface)

    versions = (Version(1, 1), Version(1, 0))
    handles = (models.RectifiedDataset, models.RectifiedStitchedMosaic,
               models.ReferenceableDataset)

    def supports(self, params):
        return (params.version in self.versions and all(
            map(lambda c: issubclass(c.real_type, self.handles),
                params.coverages)))

    def render(self, params):
        map_ = self.create_map()

        use_name = (params.version == Version(1, 0))

        for coverage in params.coverages:

            # ReferenceableDatasets are not supported in WCS < 2.0
            if issubclass(coverage.real_type, models.ReferenceableDataset):
                raise NoSuchCoverageException((coverage.identifier, ))

            data_items = self.data_items_for_coverage(coverage)
            native_format = self.get_native_format(coverage, data_items)
            layer = self.layer_for_coverage(coverage, native_format,
                                            params.version)
            map_.insertLayer(layer)

        for outputformat in self.get_all_outputformats(not use_name):
            map_.appendOutputFormat(outputformat)

        request = ms.create_request(params)
        raw_result = ms.dispatch(map_, request)
        result = result_set_from_raw_data(raw_result)
        return result
コード例 #4
0
class NativeWCS20CoverageDescriptionRenderer(Component):
    """ Coverage description renderer for WCS 2.0 using the EO application 
        profile.
    """

    implements(WCSCoverageDescriptionRendererInterface)

    versions = (Version(2, 0), )

    def supports(self, params):
        return params.version in self.versions

    def render(self, params):
        encoder = WCS20EOXMLEncoder()
        return [
            ResultBuffer(
                encoder.serialize(
                    encoder.encode_coverage_descriptions(params.coverages),
                    pretty_print=settings.DEBUG), encoder.content_type)
        ]
コード例 #5
0
    def render(self, params):
        map_ = self.create_map()

        use_name = (params.version == Version(1, 0))

        for coverage in params.coverages:

            # ReferenceableDatasets are not supported in WCS < 2.0
            if issubclass(coverage.real_type, models.ReferenceableDataset):
                raise NoSuchCoverageException((coverage.identifier, ))

            data_items = self.data_items_for_coverage(coverage)
            native_format = self.get_native_format(coverage, data_items)
            layer = self.layer_for_coverage(coverage, native_format,
                                            params.version)
            map_.insertLayer(layer)

        for outputformat in self.get_all_outputformats(not use_name):
            map_.appendOutputFormat(outputformat)

        request = ms.create_request(params)
        raw_result = ms.dispatch(map_, request)
        result = result_set_from_raw_data(raw_result)
        return result
コード例 #6
0
    def render(self, params):
        # get coverage related stuff
        coverage = params.coverage

        # ReferenceableDataset are not supported in WCS < 2.0
        if issubclass(coverage.real_type, models.ReferenceableDataset):
            raise NoSuchCoverageException((coverage.identifier, ))

        data_items = self.data_items_for_coverage(coverage)

        range_type = coverage.range_type
        bands = list(range_type)

        subsets = params.subsets

        if subsets:
            subsets.srid  # this automatically checks the validity

        # create and configure map object
        map_ = self.create_map()

        # configure outputformat
        native_format = self.get_native_format(coverage, data_items)
        if get_format_by_mime(native_format) is None:
            native_format = "image/tiff"

        frmt = params.format or native_format

        if frmt is None:
            raise RenderException("Format could not be determined", "format")

        mime_type, frmt = split_format(frmt)

        imagemode = ms.gdalconst_to_imagemode(bands[0].data_type)
        time_stamp = datetime.now().strftime("%Y%m%d%H%M%S")
        basename = "%s_%s" % (coverage.identifier, time_stamp)
        of = create_outputformat(mime_type, frmt, imagemode, basename,
                                 getattr(params, "encoding_params", {}))

        map_.appendOutputFormat(of)
        map_.setOutputFormat(of)

        # TODO: use layer factory here
        layer = self.layer_for_coverage(coverage, native_format,
                                        params.version)

        map_.insertLayer(layer)

        for connector in self.connectors:
            if connector.supports(data_items):
                break
        else:
            raise OperationNotSupportedException(
                "Could not find applicable layer connector.", "coverage")

        try:
            connector.connect(coverage, data_items, layer, {})
            # create request object and dispatch it against the map
            request = ms.create_request(
                self.translate_params(params, range_type))
            request.setParameter("format", mime_type)
            raw_result = ms.dispatch(map_, request)

        finally:
            # perform any required layer related cleanup
            connector.disconnect(coverage, data_items, layer, {})

        result_set = result_set_from_raw_data(raw_result)

        if params.version == Version(2, 0):
            if getattr(params, "mediatype",
                       None) in ("multipart/mixed", "multipart/related"):
                encoder = WCS20EOXMLEncoder()
                is_mosaic = issubclass(coverage.real_type,
                                       models.RectifiedStitchedMosaic)

                if not is_mosaic:
                    tree = encoder.alter_rectified_dataset(
                        coverage, getattr(params, "http_request", None),
                        etree.parse(result_set[0].data_file).getroot(),
                        subsets.bounding_polygon(coverage)
                        if subsets else None)
                else:
                    tree = encoder.alter_rectified_stitched_mosaic(
                        coverage.cast(), getattr(params, "http_request", None),
                        etree.parse(result_set[0].data_file).getroot(),
                        subsets.bounding_polygon(coverage)
                        if subsets else None)

                result_set[0] = ResultBuffer(encoder.serialize(tree),
                                             encoder.content_type)

        # "default" response
        return result_set
コード例 #7
0
class RectifiedCoverageMapServerRenderer(BaseRenderer):
    """ A coverage renderer for rectified coverages. Uses mapserver to process
        the request.
    """

    implements(WCSCoverageRendererInterface)

    # ReferenceableDatasets are not handled in WCS >= 2.0
    versions_full = (Version(1, 1), Version(1, 0))
    versions_partly = (Version(2, 0), )
    versions = versions_full + versions_partly

    handles_full = (models.RectifiedDataset, models.RectifiedStitchedMosaic,
                    models.ReferenceableDataset)

    handles_partly = (models.RectifiedDataset, models.RectifiedStitchedMosaic)
    handles = handles_full + handles_partly

    connectors = ExtensionPoint(ConnectorInterface)
    layer_factories = ExtensionPoint(LayerFactoryInterface)

    def supports(self, params):
        return ((params.version in self.versions_full
                 and issubclass(params.coverage.real_type, self.handles_full))
                or (params.version in self.versions_partly and issubclass(
                    params.coverage.real_type, self.handles_partly)))

    def render(self, params):
        # get coverage related stuff
        coverage = params.coverage

        # ReferenceableDataset are not supported in WCS < 2.0
        if issubclass(coverage.real_type, models.ReferenceableDataset):
            raise NoSuchCoverageException((coverage.identifier, ))

        data_items = self.data_items_for_coverage(coverage)

        range_type = coverage.range_type
        bands = list(range_type)

        subsets = params.subsets

        if subsets:
            subsets.srid  # this automatically checks the validity

        # create and configure map object
        map_ = self.create_map()

        # configure outputformat
        native_format = self.get_native_format(coverage, data_items)
        if get_format_by_mime(native_format) is None:
            native_format = "image/tiff"

        frmt = params.format or native_format

        if frmt is None:
            raise RenderException("Format could not be determined", "format")

        mime_type, frmt = split_format(frmt)

        imagemode = ms.gdalconst_to_imagemode(bands[0].data_type)
        time_stamp = datetime.now().strftime("%Y%m%d%H%M%S")
        basename = "%s_%s" % (coverage.identifier, time_stamp)
        of = create_outputformat(mime_type, frmt, imagemode, basename,
                                 getattr(params, "encoding_params", {}))

        map_.appendOutputFormat(of)
        map_.setOutputFormat(of)

        # TODO: use layer factory here
        layer = self.layer_for_coverage(coverage, native_format,
                                        params.version)

        map_.insertLayer(layer)

        for connector in self.connectors:
            if connector.supports(data_items):
                break
        else:
            raise OperationNotSupportedException(
                "Could not find applicable layer connector.", "coverage")

        try:
            connector.connect(coverage, data_items, layer, {})
            # create request object and dispatch it against the map
            request = ms.create_request(
                self.translate_params(params, range_type))
            request.setParameter("format", mime_type)
            raw_result = ms.dispatch(map_, request)

        finally:
            # perform any required layer related cleanup
            connector.disconnect(coverage, data_items, layer, {})

        result_set = result_set_from_raw_data(raw_result)

        if params.version == Version(2, 0):
            if getattr(params, "mediatype",
                       None) in ("multipart/mixed", "multipart/related"):
                encoder = WCS20EOXMLEncoder()
                is_mosaic = issubclass(coverage.real_type,
                                       models.RectifiedStitchedMosaic)

                if not is_mosaic:
                    tree = encoder.alter_rectified_dataset(
                        coverage, getattr(params, "http_request", None),
                        etree.parse(result_set[0].data_file).getroot(),
                        subsets.bounding_polygon(coverage)
                        if subsets else None)
                else:
                    tree = encoder.alter_rectified_stitched_mosaic(
                        coverage.cast(), getattr(params, "http_request", None),
                        etree.parse(result_set[0].data_file).getroot(),
                        subsets.bounding_polygon(coverage)
                        if subsets else None)

                result_set[0] = ResultBuffer(encoder.serialize(tree),
                                             encoder.content_type)

        # "default" response
        return result_set

    def translate_params(self, params, range_type):
        """ "Translate" parameters to be understandable by mapserver.
        """
        if params.version.startswith("2.0"):
            for key, value in params:
                if key == "interpolation":
                    interpolation = INTERPOLATION_TRANS.get(value)
                    if not interpolation:
                        raise InterpolationMethodNotSupportedException(
                            "Interpolation method '%s' is not supported." %
                            value)
                    yield key, value

                else:
                    yield key, value

            rangesubset = params.rangesubset
            if rangesubset:
                yield "rangesubset", ",".join(
                    map(str, rangesubset.get_band_indices(range_type, 1)))

            # TODO: this only works in newer MapServer implementations
            # (since 6.4?).
            SCALE_AVAILABLE = ms.msGetVersionInt() > 60401
            scalefactor = params.scalefactor
            if scalefactor is not None:
                if SCALE_AVAILABLE:
                    yield "scalefactor", str(scalefactor)
                else:
                    raise RenderException(
                        "'ScaleFactor' is not supported by MapServer in the "
                        "current version.", "scalefactor")

            for scale in params.scales:
                scaleaxes = []
                if isinstance(scale, ScaleSize):
                    yield "size", "%s(%d)" % (scale.axis, scale.size)
                elif isinstance(scale, ScaleExtent):
                    yield "size", "%s(%d)" % (scale.axis,
                                              scale.high - scale.low)
                elif isinstance(scale, ScaleAxis):
                    if SCALE_AVAILABLE:
                        scaleaxes.append(scale)
                    else:
                        raise RenderException(
                            "'ScaleAxes' is not supported by MapServer in the "
                            "current version.", "scaleaxes")

                if scaleaxes:
                    yield "scaleaxes", ",".join("%s(%f)" %
                                                (scale.axis, scale.scale)
                                                for scale in scaleaxes)

            if params.outputcrs is not None:
                srid = crss.parseEPSGCode(
                    params.outputcrs,
                    (crss.fromURL, crss.fromURN, crss.fromShortCode))
                if srid is None:
                    raise InvalidOutputCrsException(
                        "Failed to extract an EPSG code from the OutputCRS URI "
                        "'%s'." % params.outputcrs)
                yield "outputcrs", params.outputcrs

        else:
            for key, value in params:
                yield key, value
コード例 #8
0
class MapServerWCSCapabilitiesRenderer(BaseRenderer):
    """ WCS Capabilities renderer implementation using MapServer.
    """
    implements(WCSCapabilitiesRendererInterface)

    versions = (Version(1, 0), Version(1, 1))

    def supports(self, params):
        return params.version in self.versions

    def render(self, params):
        conf = CapabilitiesConfigReader(get_eoxserver_config())

        http_service_url = get_http_service_url(params.http_request)

        map_ = Map()
        map_.setMetaData(
            {
                "enable_request":
                "*",
                "onlineresource":
                http_service_url,
                "service_onlineresource":
                conf.onlineresource,
                "updateSequence":
                conf.update_sequence,
                "name":
                conf.name,
                "title":
                conf.title,
                "label":
                conf.title,
                "abstract":
                conf.abstract,
                "accessconstraints":
                conf.access_constraints,
                "addresstype":
                "",
                "address":
                conf.delivery_point,
                "stateorprovince":
                conf.administrative_area,
                "city":
                conf.city,
                "postcode":
                conf.postal_code,
                "country":
                conf.country,
                "contactelectronicmailaddress":
                conf.electronic_mail_address,
                "contactfacsimiletelephone":
                conf.phone_facsimile,
                "contactvoicetelephone":
                conf.phone_voice,
                "contactperson":
                conf.individual_name,
                "contactorganization":
                conf.provider_name,
                "contactposition":
                conf.position_name,
                "role":
                conf.role,
                "hoursofservice":
                conf.hours_of_service,
                "contactinstructions":
                conf.contact_instructions,
                "fees":
                conf.fees,
                "keywordlist":
                ",".join(conf.keywords),
                "formats":
                " ".join([f.wcs10name for f in self.get_wcs_formats()]),
                "srs":
                " ".join(
                    crss.getSupportedCRS_WCS(
                        format_function=crss.asShortCode)),
            },
            namespace="ows")
        map_.setProjection("EPSG:4326")

        for outputformat in self.get_all_outputformats(False):
            map_.appendOutputFormat(outputformat)

        for coverage in params.coverages:
            layer = Layer(coverage.identifier)

            render_coverage = Coverage.from_model(coverage)
            layer.setProjection(render_coverage.grid.spatial_reference.proj)
            extent = render_coverage.extent
            size = render_coverage.size
            resolution = ((extent[2] - extent[0]) / float(size[0]),
                          (extent[1] - extent[3]) / float(size[1]))

            layer.setExtent(*extent)
            layer.setMetaData(
                {
                    "title":
                    coverage.identifier,
                    "label":
                    coverage.identifier,
                    "extent":
                    "%.10g %.10g %.10g %.10g" % extent,
                    "resolution":
                    "%.10g %.10g" % resolution,
                    "size":
                    "%d %d" % size,
                    "formats":
                    " ".join([f.wcs10name for f in self.get_wcs_formats()]),
                    "srs":
                    " ".join(
                        crss.getSupportedCRS_WCS(
                            format_function=crss.asShortCode)),
                },
                namespace="wcs")

            map_.insertLayer(layer)

        request = create_request(params)
        request.setParameter("version", params.version)
        raw_result = map_.dispatch(request)
        result = result_set_from_raw_data(raw_result)
        xml_result = etree.fromstring(result[0].data)

        for elem in xml_result.xpath('//*[local-name() = "metadataLink"]'):
            elem.getparent().remove(elem)

        # Add CQL parameter to GetCapabilities operation
        for elem in xml_result.xpath(
                '//*[local-name() = "Operation"][@name = "GetCapabilities"]'):
            ows = elem.nsmap['ows']
            param = etree.SubElement(elem, '{%s}Parameter' % ows)
            param.attrib['name'] = 'cql'
            etree.SubElement(param, '{%s}AnyValue' % ows)

        xml_result_data = etree.tostring(xml_result,
                                         pretty_print=True,
                                         encoding='UTF-8',
                                         xml_declaration=True)

        result[0] = ResultBuffer(xml_result_data, result[0].content_type)
        return result
コード例 #9
0
    def render(self, params):
        # get coverage related stuff
        coverage = params.coverage

        # ReferenceableDataset are not supported in WCS < 2.0
        if params.coverage.grid.is_referenceable and params.version:
            raise NoSuchCoverageException((coverage.identifier, ))

        data_locations = self.arraydata_locations_for_coverage(coverage)

        range_type = coverage.range_type
        bands = list(range_type)

        subsets = params.subsets

        if subsets:
            subsets.srid  # this automatically checks the validity

        # create and configure map object
        map_ = self.create_map()

        env = {}
        for data_location in data_locations:
            env.update(data_location.env)
        gdal.set_env(env, False)

        # configure outputformat
        native_format = self.get_native_format(coverage, data_locations)
        if native_format and get_format_by_mime(native_format) is None:
            native_format = "image/tiff"

        frmt = params.format or native_format

        if frmt is None:
            raise RenderException("Format could not be determined", "format")

        mime_type, frmt = split_format(frmt)

        imagemode = ms.gdalconst_to_imagemode(bands[0].data_type)
        time_stamp = datetime.now().strftime("%Y%m%d%H%M%S")
        basename = "%s_%s" % (coverage.identifier, time_stamp)
        of = create_outputformat(mime_type, frmt, imagemode, basename,
                                 getattr(params, "encoding_params", {}))

        map_.appendOutputFormat(of)
        map_.setOutputFormat(of)

        # TODO: use layer factory here
        layer = self.layer_for_coverage(coverage, native_format,
                                        params.version)

        map_.insertLayer(layer)
        connector = get_connector_by_test(coverage, data_locations)

        if not connector:
            raise OperationNotSupportedException(
                "Could not find applicable layer connector.", "coverage")

        try:
            connector.connect(coverage, data_locations, layer, {})
            # create request object and dispatch it against the map
            request = ms.create_request(
                self.translate_params(params, range_type))
            request.setParameter("format", mime_type)
            raw_result = ms.dispatch(map_, request)

        finally:
            # perform any required layer related cleanup
            connector.disconnect(coverage, data_locations, layer, {})

        result_set = result_set_from_raw_data(raw_result)

        if params.version == Version(2, 0):
            mediatype = getattr(params, "mediatype", None)
            if mediatype in ("multipart/mixed", "multipart/related"):
                with vsi.TemporaryVSIFile.from_buffer(result_set[1].data) as f:
                    ds = gdal.Open(f.name)
                    grid = objects.Grid.from_gdal_dataset(ds)

                    # get the output CRS definition
                    crs = params.outputcrs or subsets.crs or 'imageCRS'
                    if crs == 'imageCRS':
                        crs = coverage.grid.coordinate_reference_system
                    grid._coordinate_reference_system = crs

                    origin = objects.Origin.from_gdal_dataset(ds)
                    size = [ds.RasterXSize, ds.RasterYSize]

                range_type = coverage.range_type
                if params.rangesubset:
                    range_type = range_type.subset(params.rangesubset)

                coverage._grid = grid
                coverage._origin = origin
                coverage._size = size
                coverage._range_type = range_type
                if isinstance(result_set[1].filename, binary_type):
                    file_name = result_set[1].filename.decode()
                else:
                    file_name = result_set[1].filename

                reference = 'cid:coverage/%s' % file_name

                encoder = WCS20EOXMLEncoder()

                if not isinstance(coverage, objects.Mosaic):
                    tree = encoder.encode_rectified_dataset(
                        coverage, getattr(params, "http_request", None),
                        reference, mime_type,
                        subsets.bounding_polygon(coverage)
                        if subsets else None)
                else:
                    tree = encoder.encode_rectified_stitched_mosaic(
                        coverage, getattr(params, "http_request", None),
                        reference, mime_type,
                        subsets.bounding_polygon(coverage)
                        if subsets else None)

                result_set[0] = ResultBuffer(encoder.serialize(tree),
                                             encoder.content_type)

        # "default" response
        return result_set
コード例 #10
0
class RectifiedCoverageMapServerRenderer(BaseRenderer):
    """ A coverage renderer for rectified coverages. Uses mapserver to process
        the request.
    """

    # ReferenceableDatasets are not handled in WCS >= 2.0
    versions_full = (Version(1, 1), Version(1, 0))
    versions_partly = (Version(2, 0), )
    versions = versions_full + versions_partly

    # handles_full = (
    #     models.RectifiedDataset,
    #     models.RectifiedStitchedMosaic,
    #     models.ReferenceableDataset
    # )

    # handles_partly = (models.RectifiedDataset, models.RectifiedStitchedMosaic)
    # handles = handles_full + handles_partly

    # connectors = ExtensionPoint(ConnectorInterface)
    # layer_factories = ExtensionPoint(LayerFactoryInterface)

    def supports(self, params):
        # return (
        #     (
        #         params.version in self.versions_full and
        #     and issubclass(params.coverage.real_type, self.handles_full))
        #     or
        #     (params.version in self.versions_partly
        #     and issubclass(params.coverage.real_type, self.handles_partly))
        # )
        return params.version in self.versions and not params.coverage.grid.is_referenceable

    def render(self, params):
        # get coverage related stuff
        coverage = params.coverage

        # ReferenceableDataset are not supported in WCS < 2.0
        if params.coverage.grid.is_referenceable and params.version:
            raise NoSuchCoverageException((coverage.identifier, ))

        data_locations = self.arraydata_locations_for_coverage(coverage)

        range_type = coverage.range_type
        bands = list(range_type)

        subsets = params.subsets

        if subsets:
            subsets.srid  # this automatically checks the validity

        # create and configure map object
        map_ = self.create_map()

        env = {}
        for data_location in data_locations:
            env.update(data_location.env)
        gdal.set_env(env, False)

        # configure outputformat
        native_format = self.get_native_format(coverage, data_locations)
        if native_format and get_format_by_mime(native_format) is None:
            native_format = "image/tiff"

        frmt = params.format or native_format

        if frmt is None:
            raise RenderException("Format could not be determined", "format")

        mime_type, frmt = split_format(frmt)

        imagemode = ms.gdalconst_to_imagemode(bands[0].data_type)
        time_stamp = datetime.now().strftime("%Y%m%d%H%M%S")
        basename = "%s_%s" % (coverage.identifier, time_stamp)
        of = create_outputformat(mime_type, frmt, imagemode, basename,
                                 getattr(params, "encoding_params", {}))

        map_.appendOutputFormat(of)
        map_.setOutputFormat(of)

        # TODO: use layer factory here
        layer = self.layer_for_coverage(coverage, native_format,
                                        params.version)

        map_.insertLayer(layer)
        connector = get_connector_by_test(coverage, data_locations)

        if not connector:
            raise OperationNotSupportedException(
                "Could not find applicable layer connector.", "coverage")

        try:
            connector.connect(coverage, data_locations, layer, {})
            # create request object and dispatch it against the map
            request = ms.create_request(
                self.translate_params(params, range_type))
            request.setParameter("format", mime_type)
            raw_result = ms.dispatch(map_, request)

        finally:
            # perform any required layer related cleanup
            connector.disconnect(coverage, data_locations, layer, {})

        result_set = result_set_from_raw_data(raw_result)

        if params.version == Version(2, 0):
            mediatype = getattr(params, "mediatype", None)
            if mediatype in ("multipart/mixed", "multipart/related"):
                with vsi.TemporaryVSIFile.from_buffer(result_set[1].data) as f:
                    ds = gdal.Open(f.name)
                    grid = objects.Grid.from_gdal_dataset(ds)

                    # get the output CRS definition
                    crs = params.outputcrs or subsets.crs or 'imageCRS'
                    if crs == 'imageCRS':
                        crs = coverage.grid.coordinate_reference_system
                    grid._coordinate_reference_system = crs

                    origin = objects.Origin.from_gdal_dataset(ds)
                    size = [ds.RasterXSize, ds.RasterYSize]

                range_type = coverage.range_type
                if params.rangesubset:
                    range_type = range_type.subset(params.rangesubset)

                coverage._grid = grid
                coverage._origin = origin
                coverage._size = size
                coverage._range_type = range_type
                if isinstance(result_set[1].filename, binary_type):
                    file_name = result_set[1].filename.decode()
                else:
                    file_name = result_set[1].filename

                reference = 'cid:coverage/%s' % file_name

                encoder = WCS20EOXMLEncoder()

                if not isinstance(coverage, objects.Mosaic):
                    tree = encoder.encode_rectified_dataset(
                        coverage, getattr(params, "http_request", None),
                        reference, mime_type,
                        subsets.bounding_polygon(coverage)
                        if subsets else None)
                else:
                    tree = encoder.encode_rectified_stitched_mosaic(
                        coverage, getattr(params, "http_request", None),
                        reference, mime_type,
                        subsets.bounding_polygon(coverage)
                        if subsets else None)

                result_set[0] = ResultBuffer(encoder.serialize(tree),
                                             encoder.content_type)

        # "default" response
        return result_set

    def translate_params(self, params, range_type):
        """ "Translate" parameters to be understandable by mapserver.
        """

        if params.version.startswith("2.0"):
            for key, value in params:
                if key == 'coverageid':
                    try:
                        models.identifier_validators[0](value)
                    except:
                        value = 'not-ncname'
                    yield key, value

                elif key == "interpolation":
                    interpolation = INTERPOLATION_TRANS.get(value)
                    if not interpolation:
                        raise InterpolationMethodNotSupportedException(
                            "Interpolation method '%s' is not supported." %
                            value)
                    yield key, value

                else:
                    yield key, value

            rangesubset = params.rangesubset
            if rangesubset:
                yield "rangesubset", ",".join(
                    map(str, rangesubset.get_band_indices(range_type, 1)))

            # TODO: this only works in newer MapServer implementations
            # (since 6.4?).
            SCALE_AVAILABLE = ms.msGetVersionInt() > 60401
            scalefactor = params.scalefactor
            if scalefactor is not None:
                if SCALE_AVAILABLE:
                    yield "scalefactor", str(scalefactor)
                else:
                    raise RenderException(
                        "'ScaleFactor' is not supported by MapServer in the "
                        "current version.", "scalefactor")

            for scale in params.scales:
                scaleaxes = []
                if isinstance(scale, ScaleSize):
                    yield "size", "%s(%d)" % (scale.axis, scale.size)
                elif isinstance(scale, ScaleExtent):
                    yield "size", "%s(%d)" % (scale.axis,
                                              scale.high - scale.low)
                elif isinstance(scale, ScaleAxis):
                    if SCALE_AVAILABLE:
                        scaleaxes.append(scale)
                    else:
                        raise RenderException(
                            "'ScaleAxes' is not supported by MapServer in the "
                            "current version.", "scaleaxes")

                if scaleaxes:
                    yield "scaleaxes", ",".join("%s(%f)" %
                                                (scale.axis, scale.scale)
                                                for scale in scaleaxes)

            if params.outputcrs is not None:
                srid = crss.parseEPSGCode(
                    params.outputcrs,
                    (crss.fromURL, crss.fromURN, crss.fromShortCode))
                if srid is None:
                    raise InvalidOutputCrsException(
                        "Failed to extract an EPSG code from the OutputCRS URI "
                        "'%s'." % params.outputcrs)
                yield "outputcrs", params.outputcrs

        else:
            for key, value in params:
                yield key, value
コード例 #11
0
class MapServerWCSCapabilitiesRenderer(BaseRenderer):
    """ WCS Capabilities renderer implementation using MapServer.
    """
    implements(WCSCapabilitiesRendererInterface)

    versions = (Version(1, 0), Version(1, 1))

    def supports(self, params):
        return params.version in self.versions

    def render(self, params):
        conf = CapabilitiesConfigReader(get_eoxserver_config())

        http_service_url = get_http_service_url(params.http_request)

        map_ = Map()
        map_.setMetaData({
            "enable_request": "*",
            "onlineresource": http_service_url,
            "service_onlineresource": conf.onlineresource,
            "updateSequence": conf.update_sequence,
            "name": conf.name,
            "title": conf.title,
            "label": conf.title,
            "abstract": conf.abstract,
            "accessconstraints": conf.access_constraints,
            "addresstype": "",
            "address": conf.delivery_point,
            "stateorprovince": conf.administrative_area,
            "city": conf.city,
            "postcode": conf.postal_code,
            "country": conf.country,
            "contactelectronicmailaddress": conf.electronic_mail_address,
            "contactfacsimiletelephone": conf.phone_facsimile,
            "contactvoicetelephone": conf.phone_voice,
            "contactperson": conf.individual_name,
            "contactorganization": conf.provider_name,
            "contactposition": conf.position_name,
            "role": conf.role,
            "hoursofservice": conf.hours_of_service,
            "contactinstructions": conf.contact_instructions,
            "fees": conf.fees,
            "keywordlist": ",".join(conf.keywords),
            "formats": " ".join([f.wcs10name for f in self.get_wcs_formats()]),
            "srs": " ".join(crss.getSupportedCRS_WCS(format_function=crss.asShortCode)),
        }, namespace="ows")
        map_.setProjection("EPSG:4326")

        for outputformat in self.get_all_outputformats(False):
            map_.appendOutputFormat(outputformat)

        for coverage in params.coverages:
            layer = Layer(coverage.identifier)

            layer.setProjection(coverage.spatial_reference.proj)
            extent = coverage.extent
            size = coverage.size
            resolution = ((extent[2] - extent[0]) / float(size[0]),
                          (extent[1] - extent[3]) / float(size[1]))

            layer.setExtent(*extent)
            layer.setMetaData({
                "title": coverage.identifier,
                "label": coverage.identifier,
                "extent": "%.10g %.10g %.10g %.10g" % extent,
                "resolution": "%.10g %.10g" % resolution,
                "size": "%d %d" % size,
                "formats": " ".join([f.wcs10name for f in self.get_wcs_formats()]),
                "srs": " ".join(crss.getSupportedCRS_WCS(format_function=crss.asShortCode)),
            }, namespace="wcs")

            map_.insertLayer(layer)

        request = create_request(params)
        request.setParameter("version", params.version)
        raw_result = map_.dispatch(request)
        result = result_set_from_raw_data(raw_result)
        return result
コード例 #12
0
class SiteRenderer(Component):
    """ A coverage renderer for VirES Products and Product Collections.
    """

    implements(WCSCoverageRendererInterface)

    versions = (Version(2, 0), )
    handles = (models.SiteDataset, )

    def supports(self, params):
        return issubclass(params.coverage.real_type, self.handles)

    def render(self, params):
        coverage = params.coverage.cast()
        frmt = params.format

        # get subset
        subset = self._apply_subsets(coverage, params.subsets)

        output_data = self._read_data(coverage, subset, params.rangesubset)

        result = self._encode_data(coverage, output_data, frmt)

        # TODO: coverage description if "multipart"
        return [result]

    def _apply_subsets(self, coverage, subsets):
        if len(subsets) > 1:
            raise InvalidSubsettingException("Too many subsets supplied")

        elif len(subsets):
            subset = subsets[0]

            if not isinstance(subset, Trim):
                raise InvalidSubsettingException(
                    "Invalid subsetting method: only trims are allowed")

            if subset.is_temporal:
                begin_time, end_time = coverage.time_extent
                if subset.low < begin_time or subset.high > end_time:
                    raise InvalidSubsettingException(
                        "Temporal subset does not match coverage temporal "
                        "extent.")

                resolution = get_total_seconds(coverage.resolution_time)
                low = get_total_seconds(subset.low - begin_time) / resolution
                high = get_total_seconds(subset.high - begin_time) / resolution

                subset = Trim("x", low, high)

            else:
                if subset.low < 0 or subset.high > coverage.size_x:
                    raise InvalidSubsettingException(
                        "Subset size does not match coverage size.")

        else:
            subset = Trim("x", 0, coverage.size_x)

        return subset

    def _read_data(self, coverage, subset, rangesubset):
        range_type = coverage.range_type

        # Open file
        filename = connect(coverage.data_items.all()[0])

        root = etree.parse(filename).getroot()
        output_data = OrderedDict()

        # Read data

        band = range_type[0]
        if not rangesubset or band in rangesubset:
            data = map(float, root.xpath("data/value/text()"))
            print data, root
            data = data[int(subset.low):int(subset.high)]
            output_data[band.identifier] = data

        return output_data

    def _encode_data(self, coverage, output_data, frmt):
        # Encode data
        if frmt == "text/csv":
            output_filename = "/tmp/%s.csv" % uuid4().hex
            with open(output_filename, "w+") as f:
                writer = csv.writer(f)
                writer.writerow(output_data.keys())
                for row in izip(*output_data.values()):
                    writer.writerow(row)

            return ResultFile(output_filename, "text/csv",
                              "%s.csv" % coverage.identifier,
                              coverage.identifier)

        else:
            raise RenderException("Invalid format '%s'" % frmt, "format")
コード例 #13
0
class GDALReferenceableDatasetRenderer(Component):
    implements(WCSCoverageRendererInterface)

    versions = (Version(2, 0), )

    def supports(self, params):
        return (issubclass(params.coverage.real_type,
                           models.ReferenceableDataset)
                and params.version in self.versions)

    def render(self, params):
        # get the requested coverage, data items and range type.
        coverage = params.coverage
        data_items = coverage.data_items.filter(semantic__startswith="bands")
        range_type = coverage.range_type

        subsets = params.subsets

        # GDAL source dataset. Either a single file dataset or a composed VRT
        # dataset.
        src_ds = self.get_source_dataset(coverage, data_items, range_type)

        # retrieve area of interest of the source image according to given
        # subsets
        src_rect, dst_rect = self.get_source_and_dest_rect(src_ds, subsets)

        # deduct "native" format of the source image
        native_format = data_items[0].format if len(data_items) == 1 else None

        # get the requested image format, which defaults to the native format
        # if available
        frmt = params.format or native_format

        if not frmt:
            raise RenderException("No format specified.", "format")

        if params.scalefactor is not None or params.scales:
            raise RenderException(
                "ReferenceableDataset cannot be scaled.",
                "scalefactor" if params.scalefactor is not None else "scale")

        maxsize = WCSConfigReader(get_eoxserver_config()).maxsize
        if maxsize is not None:
            if maxsize < dst_rect.size_x or maxsize < dst_rect.size_y:
                raise RenderException(
                    "Requested image size %dpx x %dpx exceeds the allowed "
                    "limit maxsize=%dpx." %
                    (dst_rect.size_x, dst_rect.size_y, maxsize), "size")

        # perform subsetting either with or without rangesubsetting
        subsetted_ds = self.perform_subset(src_ds, range_type, src_rect,
                                           dst_rect, params.rangesubset)

        # encode the processed dataset and save it to the filesystem
        out_ds, out_driver = self.encode(
            subsetted_ds, frmt, getattr(params, "encoding_params", {}))

        driver_metadata = out_driver.GetMetadata_Dict()
        mime_type = driver_metadata.get("DMD_MIMETYPE")
        extension = driver_metadata.get("DMD_EXTENSION")

        time_stamp = datetime.now().strftime("%Y%m%d%H%M%S")
        filename_base = "%s_%s" % (coverage.identifier, time_stamp)

        result_set = [
            ResultFile(path, mime_type, "%s.%s" % (filename_base, extension),
                       ("cid:coverage/%s" %
                        coverage.identifier) if i == 0 else None)
            for i, path in enumerate(out_ds.GetFileList())
        ]

        if params.mediatype and params.mediatype.startswith("multipart"):
            reference = "cid:coverage/%s" % result_set[0].filename

            if subsets.has_x and subsets.has_y:
                footprint = GEOSGeometry(reftools.get_footprint_wkt(out_ds))
                if not subsets.srid:
                    extent = footprint.extent
                else:
                    extent = subsets.xy_bbox
                encoder_subset = (subsets.srid, src_rect.size, extent,
                                  footprint)
            else:
                encoder_subset = None

            encoder = WCS20EOXMLEncoder()
            content = encoder.serialize(
                encoder.encode_referenceable_dataset(coverage, range_type,
                                                     reference, mime_type,
                                                     encoder_subset))
            result_set.insert(0, ResultBuffer(content, encoder.content_type))

        return result_set

    def get_source_dataset(self, coverage, data_items, range_type):
        if len(data_items) == 1:
            return gdal.OpenShared(abspath(connect(data_items[0])))
        else:
            vrt = VRTBuilder(coverage.size_x,
                             coverage.size_y,
                             vrt_filename=temp_vsimem_filename())

            # sort in ascending order according to semantic
            data_items = sorted(data_items, key=(lambda d: d.semantic))

            gcps = []
            compound_index = 0
            for data_item in data_items:
                path = abspath(connect(data_item))

                # iterate over all bands of the data item
                for set_index, item_index in self._data_item_band_indices(
                        data_item):
                    if set_index != compound_index + 1:
                        raise ValueError
                    compound_index = set_index

                    band = range_type[set_index]
                    vrt.add_band(band.data_type)
                    vrt.add_simple_source(set_index, path, item_index)

            return vrt.dataset

    def get_source_and_dest_rect(self, dataset, subsets):
        size_x, size_y = dataset.RasterXSize, dataset.RasterYSize
        image_rect = Rect(0, 0, size_x, size_y)

        if not subsets:
            subset_rect = image_rect

        # pixel subset
        elif subsets.srid is None:  # means "imageCRS"
            minx, miny, maxx, maxy = subsets.xy_bbox

            minx = int(minx) if minx is not None else image_rect.offset_x
            miny = int(miny) if miny is not None else image_rect.offset_y
            maxx = int(maxx) if maxx is not None else image_rect.upper_x
            maxy = int(maxy) if maxy is not None else image_rect.upper_y

            subset_rect = Rect(minx, miny, maxx - minx + 1, maxy - miny + 1)

        # subset in geographical coordinates
        else:
            vrt = VRTBuilder(*image_rect.size)
            vrt.copy_gcps(dataset)

            options = reftools.suggest_transformer(dataset)

            subset_rect = reftools.rect_from_subset(vrt.dataset, subsets.srid,
                                                    *subsets.xy_bbox,
                                                    **options)

        # check whether or not the subsets intersect with the image
        if not image_rect.intersects(subset_rect):
            raise RenderException("Subset outside coverage extent.", "subset")

        src_rect = subset_rect  #& image_rect # TODO: why no intersection??
        dst_rect = src_rect - subset_rect.offset

        return src_rect, dst_rect

    def perform_subset(self,
                       src_ds,
                       range_type,
                       subset_rect,
                       dst_rect,
                       rangesubset=None):
        vrt = VRTBuilder(*subset_rect.size)

        input_bands = list(range_type)

        # list of band indices/names. defaults to all bands
        if rangesubset:
            subset_bands = rangesubset.get_band_indices(range_type, 1)
        else:
            subset_bands = xrange(1, len(range_type) + 1)

        for dst_index, src_index in enumerate(subset_bands, start=1):
            input_band = input_bands[src_index - 1]
            vrt.add_band(input_band.data_type)
            vrt.add_simple_source(dst_index, src_ds, src_index, subset_rect,
                                  dst_rect)

        vrt.copy_metadata(src_ds)
        vrt.copy_gcps(src_ds, subset_rect)

        return vrt.dataset

    def encode(self, dataset, frmt, encoding_params):
        options = ()
        if frmt == "image/tiff":
            options = _get_gtiff_options(**encoding_params)

        args = [("%s=%s" % key, value) for key, value in options]

        path = "/tmp/%s" % uuid4().hex
        out_driver = gdal.GetDriverByName("GTiff")
        return out_driver.CreateCopy(path, dataset, True, args), out_driver