Example #1
0
def create_outputformat(mime_type, options, imagemode, basename, parameters):
    """ Returns a ``mapscript.outputFormatObj`` for the given format name and
        imagemode.
    """

    reg_format = get_format_by_mime(mime_type)

    if not reg_format:
        raise RenderException("Unsupported output format '%s'." % mime_type,
                              "format")

    outputformat = ms.outputFormatObj(reg_format.driver, "custom")
    outputformat.name = reg_format.wcs10name
    outputformat.mimetype = reg_format.mimeType
    outputformat.extension = reg_format.defaultExt
    outputformat.imagemode = imagemode

    #for key, value in options:
    #    outputformat.setOption(str(key), str(value))

    if mime_type == "image/tiff":
        _apply_gtiff(outputformat, **parameters)

    filename = basename + reg_format.defaultExt
    outputformat.setOption("FILENAME", str(filename))

    return outputformat
Example #2
0
 def check_parameters(self, map_, request_values):
     for key, value in request_values:
         if key.lower() == "format":
             if not map_.getOutputFormatByName(value):
                 raise InvalidFormat(value)
             break
     else:
         raise RenderException("Missing 'format' parameter")
Example #3
0
    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")
Example #4
0
    def create_dataset(self, llbbox, time, elevation, size, product, out_file):
        if size[0] != size[1]:
            raise RenderException("Size needs to be quadratic.", "width")

        resx = (llbbox[2] - llbbox[0]) / size[0]
        resy = (llbbox[3] - llbbox[1]) / size[1]

        wmmbbox = (
            llbbox[1],  # - resy,
            llbbox[0],  # - resx, 
            llbbox[3],  # + resy,
            llbbox[2],  # + resx
        )

        return main(
            out_file,
            product,
            wmmbbox,
            size[0],  # + 2, 
            elevation,
            to_year_fraction(time))
Example #5
0
    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
Example #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
Example #7
0
    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
Example #8
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
Example #9
0
    def render(self, layers, bbox, crs, size, frmt, time, elevation, styles):
        if not time:
            raise RenderException("Missing mandatory 'time' parameter.")

        try:
            time = time.value
        except AttributeError:
            raise RenderException(
                "Parameter 'time' must be a slice and not a range.")

        llbbox = self.get_llbbox(bbox, crs)

        mapfile_path = get_eoxserver_config().get("wmm", "mapfile")
        map_ = ms.mapObj(mapfile_path)  #TODO: path to map
        map_.setMetaData("ows_enable_request", "*")
        map_.setProjection("EPSG:4326")
        map_.imagecolor.setRGB(0, 0, 0)

        # set supported CRSs
        decoder = crss.CRSsConfigReader(get_eoxserver_config())
        crss_string = " ".join(
            map(lambda crs: "EPSG:%d" % crs, decoder.supported_crss_wms))
        map_.setMetaData("ows_srs", crss_string)
        map_.setMetaData("wms_srs", crss_string)

        datasources = []
        datasets = []

        for layer_name in layers:
            layer = map_.getLayerByName(layer_name)
            if not layer:
                continue

            product = layer.metadata.get("wmm_product")

            filename = self.generate_filename("tif")
            ds = self.create_dataset(llbbox, time, elevation, size, product,
                                     filename)
            datasets.append(ds)

            if layer.type == ms.MS_LAYER_LINE:
                flavor = layer.metadata.get("wmm_flavor")
                contour_steps = self.get_contour_intervals(
                    flavor, llbbox, size)
                filename = self.generate_filename("shp")
                self.generate_contours(ds, contour_steps, filename)

                layer.connectiontype = ms.MS_OGR
                layer.connection = filename
                layer.data, _ = splitext(basename(filename))

                datasources.append(filename)

        ms_request = ms.create_request(
            (("service", "WMS"), ("version", "1.3.0"), ("request", "GetMap"),
             ("layers", ",".join(layers)),
             ("bbox", "%f,%f,%f,%f" % (bbox[1], bbox[0], bbox[3], bbox[2])),
             ("crs", crs), ("width", str(size[0])), ("height", str(size[1])),
             ("styles", ",".join(styles)), ("format", frmt)))

        raw_result = ms.dispatch(map_, ms_request)
        result = result_set_from_raw_data(raw_result)

        shp_drv = ogr.GetDriverByName("ESRI Shapefile")
        # cleanup datasources and datasets
        for filename in datasources:
            shp_drv.DeleteDataSource(filename)

        for ds in datasets:
            driver = ds.GetDriver()
            for filename in ds.GetFileList():
                os.remove(filename)

        return result, get_content_type(result)
Example #10
0
    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