Пример #1
0
    def lookup_coverage(self, decoder, subsets):
        """ Default implementation of the coverage lookup. Returns the coverage
            model for the given request decoder or raises an exception if it is
            not found.
        """
        coverage_id = decoder.coverage_id

        try:
            obj = models.EOObject.objects.select_subclasses(
                models.Coverage, models.Mosaic).get(
                    Q(identifier=coverage_id)
                    & (Q(coverage__isnull=False) | Q(mosaic__isnull=False)))
        except models.EOObject.DoesNotExist:
            raise NoSuchCoverageException((coverage_id, ))

        if isinstance(obj, models.Coverage):
            return Coverage.from_model(obj)
        else:
            coverages = obj.coverages.all().order_by("begin_time")
            if subsets:
                subset_polygon = subsets.bounding_polygon(
                    Mosaic.from_model(obj, []))
                coverages = coverages.filter(
                    footprint__intersects=subset_polygon)
            return Mosaic.from_model(obj, coverages)
Пример #2
0
    def from_coverage_models(cls, band_expressions_and_ranges,
                             fields_and_coverage_models,
                             product_model):

        band_expressions, ranges = zip(*band_expressions_and_ranges)

        fields_and_coverages = {
            field_name: [
                Coverage.from_model(coverage)
                for coverage in coverages
            ]
            for field_name, coverages in fields_and_coverage_models.items()
        }

        return cls(
            product_model.identifier,
            band_expressions,
            ranges,
            fields_and_coverages, [
                fields_and_coverages[field_name][0].range_type.get_field(
                    field_name
                )
                for field_name in fields_and_coverages.keys()
            ],
            product_model.footprint
        )
Пример #3
0
    def lookup_coverages(self, decoder):
        """ Default implementation of the coverage lookup. Returns a sorted list
            of coverage models according to the decoders `coverage_ids`
            attribute. Raises a `NoSuchCoverageException` if any of the given
            IDs was not found in the database.
        """
        ids = decoder.coverage_ids

        # qs = models.Coverage.objects.filter(identifier__in=ids)
        qs = models.EOObject.objects.filter(identifier__in=ids, ).filter(
            Q(coverage__isnull=False)
            | Q(mosaic__isnull=False)).select_subclasses()

        objects = sorted(qs,
                         key=(lambda coverage: ids.index(coverage.identifier)))

        # check correct number
        if len(objects) < len(ids):
            available_ids = set([coverage.identifier for coverage in objects])
            raise NoSuchCoverageException(set(ids) - available_ids)

        return [
            Coverage.from_model(obj)
            if isinstance(obj, models.Coverage) else Mosaic.from_model(obj)
            for obj in objects
        ]
Пример #4
0
def get_coverage_object(svc_cfg, product):
    crs = svc_cfg.published_CRSs[product.native_CRS]
    bbox = product.ranges["bboxes"][product.native_CRS]

    return Coverage(
        identifier=product.name,
        eo_metadata=None,
        range_type=RangeType('%s__range_type' % product.name, [
            Field(
                index=i,
                identifier=band_label,
                description=band_label,
                definition='',
                unit_of_measure='',
                wavelength=None,
                significant_figures=None,
                allowed_values=None,
                nil_values=[(str(product.band_idx.nodata_val(band_label)), 'nodata')],
                data_type=None,
                data_type_range=None,
            ) for i, band_label in enumerate(product.band_idx.band_labels())
        ]),
        grid=Grid(
            product.native_CRS, [
                Axis(
                    crs['horizontal_coord'],
                    0,
                    product.resolution_x,
                    'm' if crs['geographic'] else 'deg'
                ),
                Axis(
                    crs['vertical_coord'],
                    0,
                    product.resolution_y,
                    'm' if crs['geographic'] else 'deg'
                ),
                IrregularAxis('time', 2, product.ranges['times'], 's')
            ]
        ),
        origin=Origin([
            min(bbox["left"], bbox["right"]),
            min(bbox["top"], bbox["bottom"])
        ]),
        size=[product.grid_high_x, product.grid_high_y],
        arraydata_locations=[],
        metadata_locations=[],
        native_format=svc_cfg.wcs_formats[svc_cfg.native_wcs_format]['mime'],
    )
Пример #5
0
def dispatch_wcs_get_capabilities(request, ows_url, config_client):
    if request.method == 'GET':
        decoder = WCS20GetCapabilitiesKVPDecoder(request.query)
    else:
        decoder = WCS20GetCapabilitiesXMLDecoder(request.body)

    encoder = WCS20GetCapabilitiesXMLEncoderExtended(ows_url)
    datasets = config_client.get_datasets()

    untimed_datasets = [
        dataset for dataset in datasets if 'timeextent' not in dataset
    ]

    timed_datasets = [
        dataset for dataset in datasets if 'timeextent' in dataset
    ]

    coverages = [
        Coverage(
            dataset['id'],
            EOMetadata(
                None,
                None,
                None  # TODO: whole world?
            ),
            get_range_type_from_dataset(dataset),
            *(get_grid(dataset) + ([], []))) for dataset in untimed_datasets
    ]

    dataset_series_set = [
        DatasetSeries(
            dataset['id'],
            None,
            make_aware(datetime.combine(dataset['timeextent'][0], time.min),
                       utc),
            make_aware(
                datetime.combine(dataset['timeextent'][1] or date.today(),
                                 time.min), utc),
        ) for dataset in timed_datasets
    ]
    return encoder.serialize(
        encoder.encode_capabilities(decoder.sections, DummyConfig(), coverages,
                                    dataset_series_set)), encoder.content_type
Пример #6
0
def get_coverage(config_client, coverage_id, dataset_name, datestr):
    dataset = config_client.get_dataset(dataset_name)
    try:
        date = datetime.strptime(datestr, '%Y-%m-%d')
    except:
        # TODO catch exact exception
        raise Exception(f'No such coverage {coverage_id}')

    grid, origin, size = get_grid(dataset)

    return Coverage(
        coverage_id,
        EOMetadata(
            date,
            date + timedelta(days=1),
            None  # TODO: whole world?
        ),
        get_range_type_from_dataset(dataset),
        grid,
        origin,
        size,
        [],
        [])
Пример #7
0
    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
Пример #8
0
    def get_layer_description(self, eo_object, raster_styles, geometry_styles):
        if isinstance(eo_object, models.Coverage):
            coverage = RenderCoverage.from_model(eo_object)
            return LayerDescription.from_coverage(coverage, raster_styles)
        elif isinstance(eo_object, models.Mosaic):
            coverage = RenderCoverage.from_model(eo_object)
            return LayerDescription.from_mosaic(coverage, raster_styles)
        elif isinstance(eo_object, (models.Product, models.Collection)):
            if getattr(eo_object, "product_type", None):
                browse_type_qs = eo_object.product_type.browse_types.all()
                mask_type_qs = eo_object.product_type.mask_types.all()
            elif getattr(eo_object, "collection_type", None):
                browse_type_qs = models.BrowseType.objects.filter(
                    product_type__allowed_collection_types__collections=
                    eo_object)
                mask_type_qs = models.MaskType.objects.filter(
                    product_type__allowed_collection_types__collections=
                    eo_object)
            else:
                browse_type_qs = models.BrowseType.objects.none()
                mask_type_qs = models.MaskType.objects.none()

            browse_types_name_and_is_gray = browse_type_qs.annotate(
                is_gray=Case(When(green_expression__isnull=True,
                                  then=Value(True)),
                             default=Value(False),
                             output_field=BooleanField())).values_list(
                                 'name', 'is_gray').distinct()
            mask_type_names = mask_type_qs.values_list('name',
                                                       flat=True).distinct()

            sub_layers = [
                LayerDescription("%s%soutlines" %
                                 (eo_object.identifier, self.suffix_separator),
                                 styles=geometry_styles,
                                 queryable=True),
                LayerDescription("%s%soutlined" %
                                 (eo_object.identifier, self.suffix_separator),
                                 styles=geometry_styles,
                                 queryable=True)
            ]
            for name, is_gray in browse_types_name_and_is_gray:
                sub_layers.append(
                    LayerDescription(
                        "%s%s%s" %
                        (eo_object.identifier, self.suffix_separator, name)
                        if name else eo_object.identifier,
                        styles=raster_styles if is_gray else []))

            for mask_type_name in mask_type_names:
                sub_layers.append(
                    LayerDescription("%s%s%s" %
                                     (eo_object.identifier,
                                      self.suffix_separator, mask_type_name),
                                     styles=geometry_styles))
                sub_layers.append(
                    LayerDescription("%s%smasked_%s" %
                                     (eo_object.identifier,
                                      self.suffix_separator, mask_type_name)))

            dimensions = {}
            if eo_object.begin_time and eo_object.end_time:
                dimensions["time"] = {
                    'min': isoformat(eo_object.begin_time),
                    'max': isoformat(eo_object.end_time),
                    'step': 'PT1S',
                    'default': isoformat(eo_object.end_time),
                    'units': 'ISO8601'
                }

            return LayerDescription(name=eo_object.identifier,
                                    bbox=eo_object.footprint.extent
                                    if eo_object.footprint else None,
                                    dimensions=dimensions,
                                    sub_layers=sub_layers)

        raise UnsupportedObject("Object %r cannot be mapped to a layer." %
                                eo_object)
Пример #9
0
    def lookup_layer(self, layer_name, suffix, style, filters_expressions,
                     sort_by, time, ranges, bands, wavelengths, elevation,
                     zoom):
        """ Lookup the layer from the registered objects.
        """
        reader = LayerMapperConfigReader(get_eoxserver_config())
        limit_products = (reader.limit_products
                          if reader.limit_mode == 'hide' else None)
        min_render_zoom = reader.min_render_zoom
        full_name = '%s%s%s' % (layer_name, self.suffix_separator, suffix)

        try:
            eo_object = models.EOObject.objects.select_subclasses(
                models.Collection, models.Product, models.Coverage,
                models.Mosaic).get(identifier=layer_name)
        except models.EOObject.DoesNotExist:
            raise NoSuchLayer('Layer %r does not exist' % layer_name)

        if isinstance(eo_object, models.Coverage):
            if suffix in ('', 'bands'):
                return CoverageLayer(full_name, style,
                                     RenderCoverage.from_model(eo_object),
                                     bands, wavelengths, time, elevation,
                                     ranges)

            elif suffix == 'outlines':
                return OutlinesLayer(name=full_name,
                                     style=style,
                                     fill=None,
                                     footprints=[eo_object.footprint])

            # TODO: masked coverages, when using the coverages product

            else:
                raise NoSuchLayer('Invalid layer suffix %r' % suffix)

        # TODO: deprecated
        elif isinstance(eo_object, models.Mosaic):
            if suffix == 'outlines':
                return OutlinesLayer(
                    name=full_name,
                    style=style,
                    fill=None,
                    footprints=[
                        coverage.footprint for coverage in self.iter_coverages(
                            eo_object, filters_expressions, sort_by)
                    ])
            else:
                return MosaicLayer(
                    full_name, style, RenderMosaic.from_model(eo_object), [
                        RenderCoverage.from_model(coverage)
                        for coverage in self.iter_coverages(
                            eo_object, filters_expressions, sort_by)
                    ], bands, wavelengths, time, elevation, ranges)

        elif isinstance(eo_object, (models.Collection, models.Product)):
            if suffix == '' or suffix == 'outlined' or suffix == 'bands':
                browses = []
                product_browses = self.iter_products_browses(
                    eo_object,
                    filters_expressions,
                    sort_by,
                    None,
                    style,
                    limit=limit_products)

                has_products = False
                for product, browse, _ in product_browses:
                    # When bands/wavelengths are specifically requested, make a
                    # generated browse
                    if bands or wavelengths:
                        browse = _generate_browse_from_bands(
                            product, bands, wavelengths, ranges)
                        if browse:
                            browses.append(browse)
                            has_products = True

                    # When available use the default browse
                    elif browse:
                        browses.append(Browse.from_model(product, browse))
                        has_products = True

                    # As fallback use the default browse type (with empty name)
                    # to generate a browse from the specified bands
                    else:
                        browse_type = product.product_type.browse_types.filter(
                            name='').first()
                        if browse_type:
                            browse = _generate_browse_from_browse_type(
                                product, browse_type)
                            if browse:
                                browses.append(browse)
                                has_products = True

                if not has_products:
                    coverages = self.iter_coverages(eo_object,
                                                    filters_expressions,
                                                    sort_by)

                    if suffix == '':
                        return CoveragesLayer(full_name, style, [
                            RenderCoverage.from_model(coverage)
                            for coverage in coverages
                        ], bands, wavelengths, time, elevation, ranges)
                    else:
                        return OutlinedCoveragesLayer(full_name, style, [
                            RenderCoverage.from_model(coverage)
                            for coverage in coverages
                        ], bands, wavelengths, time, elevation, ranges)

                # detect whether we are below the zoom limit
                if min_render_zoom is None or zoom >= min_render_zoom:
                    # either return the simple browse layer or the outlined one
                    if suffix == '':
                        return BrowseLayer(name=full_name,
                                           style=style,
                                           browses=browses,
                                           ranges=ranges)
                    else:
                        return OutlinedBrowseLayer(name=full_name,
                                                   style=style,
                                                   browses=browses,
                                                   ranges=ranges)

                # render outlines when we are below the zoom limit
                else:
                    return OutlinesLayer(name=full_name,
                                         style=reader.color,
                                         fill=reader.fill_opacity,
                                         footprints=[
                                             product.footprint
                                             for product in self.iter_products(
                                                 eo_object,
                                                 filters_expressions,
                                                 sort_by,
                                                 limit=limit_products)
                                         ])

            elif suffix == 'outlines':
                return OutlinesLayer(
                    name=full_name,
                    style=style,
                    fill=None,
                    footprints=[
                        product.footprint
                        for product in self.iter_products(eo_object,
                                                          filters_expressions,
                                                          sort_by,
                                                          limit=limit_products)
                    ])

            elif suffix.startswith('outlines_masked_'):
                post_suffix = suffix[len('outlines_masked_'):]

                product_browses_mask = self.iter_products_browses_masks(
                    eo_object,
                    filters_expressions,
                    sort_by,
                    post_suffix,
                    limit=limit_products)
                footprints = []
                masks = []
                for product, browse, mask, mask_type in product_browses_mask:
                    footprints.append(product.footprint)
                    masks.append(Mask.from_model(mask, mask_type))

                return OutlinesLayer(
                    name=full_name,
                    style=style,
                    fill=None,
                    footprints=footprints,
                    masks=masks,
                )

            elif suffix.startswith('masked_'):
                post_suffix = suffix[len('masked_'):]
                mask_type = self.get_mask_type(eo_object, post_suffix)

                if not mask_type:
                    raise NoSuchLayer('No such mask type %r' % post_suffix)

                masked_browses = []

                product_browses_mask = self.iter_products_browses_masks(
                    eo_object,
                    filters_expressions,
                    sort_by,
                    post_suffix,
                    limit=limit_products)
                for product, browse, mask, mask_type in product_browses_mask:
                    # When bands/wavelengths are specifically requested, make a
                    # generated browse
                    if bands or wavelengths:
                        masked_browses.append(
                            MaskedBrowse(browse=_generate_browse_from_bands(
                                product, bands, wavelengths, ranges),
                                         mask=Mask.from_model(mask,
                                                              mask_type)))

                    # When available use the default browse
                    elif browse:
                        masked_browses.append(
                            MaskedBrowse.from_models(product, browse, mask,
                                                     mask_type))

                    # As fallback use the default browse type (with empty name)
                    # to generate a browse from the specified bands
                    else:
                        browse_type = product.product_type.browse_types.filter(
                            name='').first()
                        if browse_type:
                            masked_browses.append(
                                MaskedBrowse(
                                    browse=_generate_browse_from_browse_type(
                                        product, browse_type),
                                    mask=Mask.from_model(mask, mask_type)))

                return MaskedBrowseLayer(name=full_name,
                                         style=style,
                                         masked_browses=masked_browses)

            else:
                # either browse type or mask type
                browse_type = self.get_browse_type(eo_object, suffix)
                if browse_type:
                    browses = []

                    product_browses = self.iter_products_browses(
                        eo_object,
                        filters_expressions,
                        sort_by,
                        suffix,
                        style,
                        limit=limit_products)

                    for product, browse, browse_type in product_browses:
                        # check if a browse is already available for that
                        # browse type.
                        if browse:
                            browses.append(Browse.from_model(product, browse))

                        # if no browse is available for that browse type,
                        # generate a new browse with the instructions of that
                        # browse type
                        else:
                            browse = _generate_browse_from_browse_type(
                                product, browse_type)
                            if browse:
                                browses.append(browse)

                    return BrowseLayer(name=full_name,
                                       style=style,
                                       ranges=ranges,
                                       browses=browses)

                mask_type = self.get_mask_type(eo_object, suffix)
                if mask_type:
                    return MaskLayer(
                        name=full_name,
                        style=style,
                        masks=[
                            Mask.from_model(mask_model, mask_type)
                            for _, mask_model in self.iter_products_masks(
                                eo_object,
                                filters_expressions,
                                sort_by,
                                suffix,
                                limit=limit_products)
                        ])

                raise NoSuchLayer('Invalid layer suffix %r' % suffix)