예제 #1
0
 def serialize(self, value, jsonapi_format=False):
     return shapely_to_geojson(value)
예제 #2
0
    def paged_search(self,
                     products=None,
                     sat_ids=None,
                     date="acquired",
                     place=None,
                     geom=None,
                     start_datetime=None,
                     end_datetime=None,
                     cloud_fraction=None,
                     cloud_fraction_0=None,
                     fill_fraction=None,
                     storage_state=None,
                     q=None,
                     limit=100,
                     fields=None,
                     dltile=None,
                     sort_field=None,
                     sort_order="asc",
                     randomize=None,
                     continuation_token=None,
                     **kwargs):
        """
        Execute a metadata query in a paged manner, with up to 10,000 items per page.

        Most clients should use :py:func:`features` instead, which batch searches into smaller requests
        and handles the paging for you.

        :param list(str) products: Product Identifier(s).
        :param list(str) sat_ids: Satellite identifier(s).
        :param str date: The date field to use for search (default is `acquired`).
        :param str place: A slug identifier to be used as a region of interest.
        :param str geom: A GeoJSON or WKT region of interest or a Shapely shape object.
        :param str start_datetime: Desired starting timestamp, in any common format.
        :param str end_datetime: Desired ending timestamp, in any common format.
        :param float cloud_fraction: Maximum cloud fraction, calculated by data provider.
        :param float cloud_fraction_0: Maximum cloud fraction, calculated by cloud mask pixels.
        :param float fill_fraction: Minimum scene fill fraction, calculated as valid/total pixels.
        :param str storage_state: Filter results based on `storage_state` value. Allowed values are
            `"available"`, `"remote"`, or `None`, which returns all results regardless of
            `storage_state` value.
        :param ~descarteslabs.common.property_filtering.filtering.Expression q:
            Expression for filtering the results. See
            :py:attr:`~descarteslabs.client.services.metadata.properties`.
        :param int limit: Maximum number of items per page to return.
        :param list(str) fields: Properties to return.
        :param str dltile: A dltile key used to specify the search geometry, an alternative
            to the ``geom`` argument.
        :param str sort_field: Property to sort on.
        :param str sort_order: Order of sort.
        :param bool randomize: Randomize the results. You may also use an `int` or `str` as an explicit seed.
        :param str continuation_token: None for new query, or the `properties.continuation_token` value from
            the returned FeatureCollection from a previous invocation of this method to page through a large
            result set.

        :return: GeoJSON ``FeatureCollection`` containing at most `limit` features.
        :rtype: DotDict
        """
        check_deprecated_kwargs(
            kwargs,
            {
                "product": "products",
                "const_id": "const_ids",
                "sat_id": "sat_ids",
                "start_time": "start_datetime",
                "end_time": "end_datetime",
                "offset": None,
            },
        )

        if place:
            places = Places()
            places.auth = self.auth
            shape = places.shape(place, geom="low")
            geom = json.dumps(shape["geometry"])

        if dltile is not None:
            if isinstance(dltile, string_types):
                dltile = self._raster.dltile(dltile)
            if isinstance(dltile, dict):
                geom = dltile["geometry"]

        if isinstance(geom, dict):
            geom = json.dumps(geom)

        kwargs.update({"date": date, "limit": limit})

        if sat_ids:
            if isinstance(sat_ids, string_types):
                sat_ids = [sat_ids]

            kwargs["sat_ids"] = sat_ids

        if products:
            if isinstance(products, string_types):
                products = [products]

            kwargs["products"] = products

        if geom:
            geom = shapely_to_geojson(geom)
            kwargs["geom"] = geom

        if start_datetime:
            kwargs["start_datetime"] = start_datetime

        if end_datetime:
            kwargs["end_datetime"] = end_datetime

        if cloud_fraction is not None:
            kwargs["cloud_fraction"] = cloud_fraction

        if cloud_fraction_0 is not None:
            kwargs["cloud_fraction_0"] = cloud_fraction_0

        if fill_fraction is not None:
            kwargs["fill_fraction"] = fill_fraction

        if storage_state:
            kwargs["storage_state"] = storage_state

        if fields is not None:
            kwargs["fields"] = fields

        if q is not None:
            if not isinstance(q, list):
                q = [q]
            kwargs["query_expr"] = AndExpression(q).serialize()

        if sort_field is not None:
            kwargs["sort_field"] = sort_field

        if sort_order is not None:
            kwargs["sort_order"] = sort_order

        if randomize is not None:
            kwargs["random_seed"] = randomize

        if continuation_token is not None:
            kwargs["continuation_token"] = continuation_token

        r = self.session.post("/search", json=kwargs)

        fc = {"type": "FeatureCollection", "features": r.json()}

        if "x-continuation-token" in r.headers:
            fc["properties"] = {
                "continuation_token": r.headers["x-continuation-token"]
            }

        return DotDict(fc)
예제 #3
0
    def summary(self,
                products=None,
                sat_ids=None,
                date="acquired",
                interval=None,
                place=None,
                geom=None,
                start_datetime=None,
                end_datetime=None,
                cloud_fraction=None,
                cloud_fraction_0=None,
                fill_fraction=None,
                storage_state=None,
                q=None,
                pixels=None,
                dltile=None,
                **kwargs):
        """Get a summary of the results for the specified spatio-temporal query.

        :param list(str) products: Product identifier(s).
        :param list(str) sat_ids: Satellite identifier(s).
        :param str date: The date field to use for search (e.g. `acquired`).
        :param str interval: Part of the date to aggregate over (e.g. `day`).
            The list of possibilites is:

            * ``year`` or ``y``
            * ``quarter``
            * ``month`` or ``M``
            * ``week`` or ``q``
            * ``day`` or ``d``
            * ``hour`` or ``h``
            * ``minute`` or ``m``
            * ``product``
        :param str place: A slug identifier to be used as a region of interest.
        :param str geom: A GeoJSON or WKT region of interest or a Shapely shape object.
        :param str start_datetime: Desired starting timestamp, in any common format.
        :param str end_datetime: Desired ending timestamp, in any common format.
        :param float cloud_fraction: Maximum cloud fraction, calculated by data provider.
        :param float cloud_fraction_0: Maximum cloud fraction, calculated by cloud mask pixels.
        :param float fill_fraction: Minimum scene fill fraction, calculated as valid/total pixels.
        :param str storage_state: Filter results based on `storage_state` value. Allowed values are `"available"`,
            `"remote"`, or `None`, which returns all results regardless of `storage_state` value.
        :param ~descarteslabs.common.property_filtering.filtering.Expression q:
            Expression for filtering the results. See
            :py:attr:`~descarteslabs.client.services.metadata.properties`.
        :param bool pixels: Whether to include pixel counts in summary calculations.
        :param str dltile: A dltile key used to specify the search geometry, an alternative
            to the ``geom`` argument.

        :return: Dictionary containing summary of products that match query. Empty products list
            if no matching products found.
        :rtype: DotDict

        Example::

            >>> from descarteslabs.client.services import Metadata
            >>> iowa_geom = {
            ...     "coordinates": [[
            ...         [-96.498997, 42.560832],
            ...         [-95.765645, 40.585208],
            ...         [-91.729115, 40.61364],
            ...         [-91.391613, 40.384038],
            ...         [-90.952233, 40.954047],
            ...         [-91.04589, 41.414085],
            ...         [-90.343228, 41.587833],
            ...         [-90.140613, 41.995999],
            ...         [-91.065059, 42.751338],
            ...         [-91.217706, 43.50055],
            ...         [-96.599191, 43.500456],
            ...         [-96.498997, 42.560832]
            ...     ]],
            ...     "type": "Polygon"
            ... }
            >>> Metadata().summary(geom=iowa_geom,
            ...                    products=['landsat:LC08:PRE:TOAR'],
            ...                    start_datetime='2016-07-06',
            ...                    end_datetime='2016-07-07',
            ...                    interval='hour',
            ...                    pixels=True)
            {
              'bytes': 93298309,
              'count': 1,
              'items': [
                {
                  'bytes': 93298309,
                  'count': 1,
                  'date': '2016-07-06T16:00:00.000Z',
                  'pixels': 250508160,
                  'timestamp': 1467820800
                }
              ],
              'pixels': 250508160,
              'products': ['landsat:LC08:PRE:TOAR']
            }
        """
        check_deprecated_kwargs(
            kwargs,
            {
                "product": "products",
                "const_id": "const_ids",
                "sat_id": "sat_ids",
                "start_time": "start_datetime",
                "end_time": "end_datetime",
                "part": "interval",
            },
        )

        if place:
            places = Places()
            places.auth = self.auth
            shape = places.shape(place, geom="low")
            geom = json.dumps(shape["geometry"])

        if dltile is not None:
            if isinstance(dltile, string_types):
                dltile = self._raster.dltile(dltile)
            if isinstance(dltile, dict):
                geom = dltile["geometry"]

        if isinstance(geom, dict):
            geom = json.dumps(geom)

        if sat_ids:
            if isinstance(sat_ids, string_types):
                sat_ids = [sat_ids]

            kwargs["sat_ids"] = sat_ids

        if products:
            if isinstance(products, string_types):
                products = [products]

            kwargs["products"] = products

        if date:
            kwargs["date"] = date

        if interval:
            kwargs["interval"] = interval

        if geom:
            geom = shapely_to_geojson(geom)
            kwargs["geom"] = geom

        if start_datetime:
            kwargs["start_datetime"] = start_datetime

        if end_datetime:
            kwargs["end_datetime"] = end_datetime

        if cloud_fraction is not None:
            kwargs["cloud_fraction"] = cloud_fraction

        if cloud_fraction_0 is not None:
            kwargs["cloud_fraction_0"] = cloud_fraction_0

        if fill_fraction is not None:
            kwargs["fill_fraction"] = fill_fraction

        if q is not None:
            if not isinstance(q, list):
                q = [q]
            kwargs["query_expr"] = AndExpression(q).serialize()

        if pixels:
            kwargs["pixels"] = pixels

        if storage_state:
            kwargs["storage_state"] = storage_state

        r = self.session.post("/summary", json=kwargs)
        return DotDict(r.json())
예제 #4
0
    def dltiles_from_shape(self, resolution, tilesize, pad, shape):
        """
        Return a feature collection of DLTile GeoJSONs that intersect
        a GeoJSON geometry ``shape`` or a Shapely shape object.

        :param float resolution: Resolution of DLTile
        :param int tilesize: Number of valid pixels per DLTile
        :param int pad: Number of ghost pixels per DLTile (overlap among tiles)
        :param str shape: A GeoJSON geometry specifying a shape over
            which to intersect DLTiles

        :return: GeoJSON FeatureCollection of intersecting DLTile geometries.
        :rtype: DotDict

        :raises descarteslabs.client.exceptions.BadRequestError: if the given
            parameters would generate too many tiles - use
            :meth:`Raster.iter_dltiles_from_shape` to iterate over more

        Example::

            >>> from descarteslabs.client.services import Raster
            >>> iowa_geom = {
            ...     "coordinates": [[
            ...         [-96.498997, 42.560832],
            ...         [-95.765645, 40.585208],
            ...         [-91.729115, 40.61364],
            ...         [-91.391613, 40.384038],
            ...         [-90.952233, 40.954047],
            ...         [-91.04589, 41.414085],
            ...         [-90.343228, 41.587833],
            ...         [-90.140613, 41.995999],
            ...         [-91.065059, 42.751338],
            ...         [-91.217706, 43.50055],
            ...         [-96.599191, 43.500456],
            ...         [-96.498997, 42.560832]
            ...     ]],
            ...     "type": "Polygon"
            ... }
            >>> tiles = Raster().dltiles_from_shape(30.0, 2048, 16, iowa_geom)
            >>> tiles['features'][0]
            {
              'geometry': {
                'coordinates': [
                  [
                    [-96.81264975325402, 41.045203319986356],
                    [-96.07101667769108, 41.02873098016475],
                    [-96.04576296033223, 41.59007261142797],
                    [-96.79377566762066, 41.6068715494603...],
                    ...
                  ]
                ],
                'type': 'Polygon'
              },
              'properties': {
                'cs_code': 'EPSG:32614',
                'geotrans': [
                  683840.0,
                  30.0,
                  0,
                  4608480.0,
                  ...
                ],
                'key': '2048:16:30.0:14:3:74',
                'outputBounds': [683840.0, 4546080.0, 746240.0, 4608480.0],
                'pad': 16,
                'proj4': '+proj=utm +zone=14 +datum=WGS84 +units=m +no_defs ',
                'resolution': 30.0,
                'ti': 3,
                'tilesize': 2048,
                'tj': 74,
                'wkt': 'PROJCS["WGS 84 / UTM zone 14N",GEOGCS["WGS...Northing",NORTH],AUTHORITY["EPSG","32614"]]',
                'zone': 14
              },
              'type': 'Feature'
            }
        """
        shape = shapely_to_geojson(shape)
        return DotDict(
            type="FeatureCollection",
            features=list(
                self.iter_dltiles_from_shape(resolution, tilesize, pad, shape)
            ),
        )
예제 #5
0
    def iter_dltiles_from_shape(self, resolution, tilesize, pad, shape, maxtiles=None):
        """
        Iterates over all DLTiles as GeoJSONs features that intersect the
        GeoJSON geometry ``shape`` or Shapely shape object.

        :param float resolution: Resolution of DLTile
        :param int tilesize: Number of valid pixels per DLTile
        :param int pad: Number of ghost pixels per DLTile (overlap among tiles)
        :param str shape: A GeoJSON geometry or Shapely shape specifying a shape over
            which to intersect DLTiles.

        :return: An iterator over GeoJSON features representing
            intersecting DLTiles
        :rtype: generator(DotDict)

        Example::

            >>> iowa_geom = {
            ...     "coordinates": [[
            ...         [-96.498997, 42.560832],
            ...         [-95.765645, 40.585208],
            ...         [-91.729115, 40.61364],
            ...         [-91.391613, 40.384038],
            ...         [-90.952233, 40.954047],
            ...         [-91.04589, 41.414085],
            ...         [-90.343228, 41.587833],
            ...         [-90.140613, 41.995999],
            ...         [-91.065059, 42.751338],
            ...         [-91.217706, 43.50055],
            ...         [-96.599191, 43.500456],
            ...         [-96.498997, 42.560832]
            ...     ]],
            ...     "type": "Polygon"
            ... }
            >>> next(Raster().iter_dltiles_from_shape(30.0, 2048, 16, iowa_geom))
            {
              'geometry': {
                'coordinates': [
                  [
                    [-96.81264975325402, 41.045203319986356],
                    [-96.07101667769108, 41.02873098016475],
                    [-96.04576296033223, 41.59007261142797],
                    [-96.79377566762066, 41.6068715494603...],
                    ...
                  ]
                ],
                'type': 'Polygon'
              },
              'properties': {
                'cs_code': 'EPSG:32614',
                'geotrans': [
                  683840.0,
                  30.0,
                  0,
                  4608480.0,
                  ...
                ],
                'key': '2048:16:30.0:14:3:74',
                'outputBounds': [683840.0, 4546080.0, 746240.0, 4608480.0],
                'pad': 16,
                'proj4': '+proj=utm +zone=14 +datum=WGS84 +units=m +no_defs ',
                'resolution': 30.0,
                'ti': 3,
                'tilesize': 2048,
                'tj': 74,
                'wkt': 'PROJCS["WGS 84 / UTM zone 14N",GEOGCS["WGS...Northing",NORTH],AUTHORITY["EPSG","32614"]]',
                'zone': 14
              },
              'type': 'Feature'
            }
        """

        if maxtiles is not None:
            warnings.warn(
                "The maxtiles argument is deprecated and will be removed in a future "
                "release.",
                FutureWarning,
            )

        shape = shapely_to_geojson(shape)
        shape = as_json_string(shape)
        params = {
            "resolution": resolution,
            "tilesize": tilesize,
            "pad": pad,
            "shape": shape,
            "maxtiles": 5000,
        }

        while True:
            r = self.session.post("/dlkeys/from_shape", json=params)
            fc = DotDict(r.json())
            for t in fc.features:
                yield t
            iterstate = fc.get("iterstate", None)
            if iterstate:
                params["start_zone"] = iterstate.start_zone
                params["start_ti"] = iterstate.start_ti
                params["start_tj"] = iterstate.start_tj
            else:
                break
예제 #6
0
 def test_serialize_geometry(self):
     i = Image(name="myimage", product_id="p1", geometry=self.geometry)
     assert shapely_to_geojson(i.geometry) == i.serialize()["geometry"]