Esempio n. 1
0
    def change_image(self,
                     product_id,
                     image_id,
                     add_namespace=False,
                     **kwargs):
        """Update an image metadata entry of a product.

        :param str product_id: (Required) Product to which this image belongs.
        :param str image_id: (Required) ID of the image to modify.
        :param bool add_namespace: Add your user namespace to the product_id. *Deprecated*

        .. note::
            - See :meth:`Catalog.add_image` for additional kwargs.

        :return: JSON API representation of the image.
        :rtype: dict
        """
        check_deprecated_kwargs(kwargs, {"bpp": "bits_per_pixel"})
        if add_namespace:
            check_deprecated_kwargs(locals(), {"add_namespace": None})
            product_id = self.namespace_product(product_id)
        r = self.session.patch("/products/{}/images/{}".format(
            product_id, image_id),
                               json=kwargs)
        return r.json()
Esempio n. 2
0
    def _do_upload(self, file_ish, product_id, metadata=None):
        # kwargs are treated as metadata fields and restricted to primitives
        # for the key val pairs.
        fd = None
        product_id = self.namespace_product(product_id)

        if metadata is None:
            metadata = {}
        metadata.setdefault('process_controls', {'upload_type': 'file'})
        check_deprecated_kwargs(metadata, {"bpp": "bits_per_pixel"})

        if isinstance(file_ish, io.IOBase):
            if 'b' not in file_ish.mode:
                file_ish = io.open(file_ish.name, 'rb')
            fd = file_ish
        elif isinstance(file_ish,
                        six.string_types) and os.path.exists(file_ish):
            fd = io.open(file_ish, 'rb')
        else:
            return 1, file_ish, Exception(
                'Could not handle file: `{}` pass a valid path or open IOBase instance'
                .format(file_ish))
        try:
            r = self.session.post('/products/{}/images/upload/{}'.format(
                product_id,
                metadata.pop('image_id', None) or os.path.basename(fd.name)),
                                  json=metadata)
            upload_url = r.text
            r = self._gcs_upload_service.session.put(upload_url, data=fd)
        except (ServerError, RequestException) as e:
            return 1, fd.name, e
        finally:
            fd.close()

        return 0, fd.name, ''
Esempio n. 3
0
    def replace_image(self,
                      product_id,
                      image_id,
                      add_namespace=False,
                      **kwargs):
        """Replace image metadata with a new version.

        :param str product_id: (Required) Product to which this image belongs.
        :param str image_id: (Required) ID of the image to replace.
        :param bool add_namespace: Add your user namespace to the product_id. *Deprecated*

        .. note::
            - See :meth:`Catalog.add_image` for additional kwargs.

        :return: JSON API representation of the image.
        :rtype: dict
        """

        check_deprecated_kwargs(kwargs, {"bpp": "bits_per_pixel"})
        if add_namespace:
            product_id = self.namespace_product(product_id)

        r = self.session.put('/products/{}/images/{}'.format(
            product_id, image_id),
                             json=kwargs)
        return r.json()
Esempio n. 4
0
    def upload_image(self,
                     files,
                     product_id,
                     metadata=None,
                     multi=False,
                     image_id=None,
                     **kwargs):
        """Upload an image for a product you own.

        :param str|file|list(str)|list(file) files: (Required) a reference to the file to upload.
        :param str product_id: (Required) The id of the product this image belongs to.
        :param dict metadata: Image metadata to use instead of the computed default values.

        .. note::
            - See :meth:`Catalog.add_image` for additional kwargs.
        """

        if metadata is None:
            metadata = {}
        metadata.update(kwargs)
        check_deprecated_kwargs(metadata, {"bpp": "bits_per_pixel"})
        if multi is True:
            if not hasattr(files, '__iter__'):
                raise ValueError(
                    "Using `multi=True` requires `files` to be iterable")
            elif image_id is None:
                raise ValueError(
                    "Using `multi=True` requires `image_id` to be specified")
            else:
                upload = self._do_multi_file_upload(files, product_id,
                                                    image_id, metadata)
        else:
            upload = self._do_upload(files, product_id, metadata=metadata)
        if upload[0]:
            raise upload[2]
Esempio n. 5
0
 def _add_core_product(self, product_id, **kwargs):
     kwargs["id"] = product_id
     check_deprecated_kwargs(
         kwargs, {"start_time": "start_datetime", "end_time": "end_datetime"}
     )
     r = self.session.post("/core/products", json=kwargs)
     return r.json()
Esempio n. 6
0
    def get_product(self, product_id, add_namespace=False):
        if add_namespace:
            check_deprecated_kwargs(locals(), {"add_namespace": None})
            product_id = self.namespace_product(product_id)

        r = self.session.get("/products/{}".format(product_id))
        return r.json()
Esempio n. 7
0
 def _add_core_image(self, product_id, image_id, **kwargs):
     check_deprecated_kwargs(kwargs, {"bpp": "bits_per_pixel"})
     kwargs["id"] = image_id
     r = self.session.post(
         "/core/products/{}/images".format(product_id), json=kwargs
     )
     return r.json()
Esempio n. 8
0
    def replace_band(self,
                     product_id,
                     name,
                     srcband=None,
                     dtype=None,
                     nbits=None,
                     data_range=None,
                     add_namespace=False,
                     type=None,
                     **kwargs):
        """Replaces an existing data band with a new document.

        :param str product_id: (Required) Product to which this band will belong.
        :param str name: (Required) Name of this band.

        .. note::
            - See :meth:`Catalog.add_band` for additional kwargs.

        :return: JSON API representation of the band.
        :rtype: dict
        """

        for k, v in locals().items():
            if k in ["data_range", "dtype", "nbits", "srcband", "type"]:
                if v is None:
                    raise TypeError("required arg `{}` not provided".format(k))
                kwargs[k] = v
        if add_namespace:
            check_deprecated_kwargs(locals(), {"add_namespace": None})
            product_id = self.namespace_product(product_id)

        r = self.session.put("/products/{}/bands/{}".format(product_id, name),
                             json=kwargs)
        return r.json()
Esempio n. 9
0
    def products(self,
                 bands=None,
                 limit=None,
                 offset=None,
                 owner=None,
                 text=None,
                 **kwargs):
        """Search products that are available on the platform.

        :param list(str) bands: Band name(s) e.g ["red", "nir"] to filter products by.
                                Note that products must match all bands that are passed.
        :param int limit: Number of results to return.
        :param int offset: Index to start at when returning results.
        :param str owner: Filter products by the owner's uuid.
        :param str text: Filter products by string match.

        """
        params = ["limit", "offset", "bands", "owner", "text"]

        args = locals()
        kwargs = dict(
            kwargs, **{
                param: args[param]
                for param in params if args[param] is not None
            })
        check_deprecated_kwargs(kwargs, {"band": "bands"})

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

        return DotList(r.json())
Esempio n. 10
0
    def upload_image(self,
                     files,
                     product_id,
                     metadata=None,
                     multi=False,
                     image_id=None,
                     add_namespace=False,
                     **kwargs):
        """Upload an image for a product you own.

        This is an asynchronous operation and you can query for the status
        using `Catalog.upload_result()` with the upload_id returned by this
        method.  The upload id is the image_id, which defaults to the
        name of the file to be uploaded.

        :param str|file|list(str)|list(file) files: (Required) a reference to the file to upload.
        :param str product_id: (Required) The id of the product this image belongs to.
        :param dict metadata: Image metadata to use instead of the computed default values.
        :param bool add_namespace: Add your user namespace to the product_id. *Deprecated*

        :return: The upload id.
        :rtype: str

        .. note::
            - See :meth:`Catalog.add_image` for additional kwargs.
        """

        if metadata is None:
            metadata = {}

        metadata.update(kwargs)
        check_deprecated_kwargs(metadata, {"bpp": "bits_per_pixel"})

        if multi is True:
            if not hasattr(files, "__iter__"):
                raise ValueError(
                    "Using `multi=True` requires `files` to be iterable")
            elif image_id is None:
                raise ValueError(
                    "Using `multi=True` requires `image_id` to be specified")
            else:
                failed, upload_id, error = self._do_multi_file_upload(
                    files,
                    product_id,
                    image_id,
                    metadata,
                    add_namespace=add_namespace)
        else:
            failed, upload_id, error = self._do_upload(
                files,
                product_id,
                metadata=metadata,
                add_namespace=add_namespace)

        if failed:
            raise error

        return upload_id
Esempio n. 11
0
    def _do_upload(self,
                   file_ish,
                   product_id,
                   metadata=None,
                   add_namespace=False):
        # kwargs are treated as metadata fields and restricted to primitives
        # for the key val pairs.
        fd = None
        upload_id = None

        if add_namespace:
            check_deprecated_kwargs(locals(), {"add_namespace": None})
            product_id = self.namespace_product(product_id)

        if metadata is None:
            metadata = {}

        metadata.setdefault("process_controls", {"upload_type": "file"})
        check_deprecated_kwargs(metadata, {"bpp": "bits_per_pixel"})

        if not isinstance(product_id, six.string_types):
            raise TypeError("product_id={} is invalid. "
                            "product_id must be a string.".format(product_id))

        if isinstance(file_ish, io.IOBase):
            if "b" not in file_ish.mode:
                file_ish.close()
                file_ish = io.open(file_ish.name, "rb")

            fd = file_ish
        elif isinstance(file_ish,
                        six.string_types) and os.path.exists(file_ish):
            fd = io.open(file_ish, "rb")
        else:
            e = Exception("Could not handle file: `{}` pass a valid path "
                          "or open IOBase file".format(file_ish))
            return True, upload_id, e

        try:
            upload_id = metadata.pop("image_id", None) or os.path.basename(
                fd.name)

            r = self.session.post(
                "/products/{}/images/upload/{}".format(product_id, upload_id),
                json=metadata,
            )
            upload_url = r.text
            r = self._gcs_upload_service.session.put(upload_url, data=fd)
        except (ServerError, RequestException) as e:
            return True, upload_id, e
        except NotFoundError as e:
            raise NotFoundError(
                "Make sure product_id exists in the catalog before \
            attempting to upload data. %s" % e.message)
        finally:
            fd.close()

        return False, upload_id, None
Esempio n. 12
0
    def replace_product(
        self,
        product_id,
        title,
        description,
        add_namespace=False,
        set_global_permissions=False,
        **kwargs
    ):
        """Replace a product in your catalog with a new version.

        :param str product_id: (Required) A unique name for this product.
        :param str title: (Required) Official product title.
        :param str description: (Required) Information about the product,
                                why it exists, and what it provides.

        :param bool add_namespace: Add your user namespace to the product_id. *Deprecated*
        :param list(str) read: A list of groups, or user hashes to give read access to.
        :param int spectral_bands: Number of spectral bands the product has.
        :param list(str) native_bands: A list of the names of the native bands of this product
                                        (most applicable to satellite sensors).
        :param str start_datetime: ISO8601 compliant date string, indicating start of product data.
        :param str end_datetime: ISO8601 compliant date string, indicating end of product data.
        :param str notes: Any notes to relay about the product.
        :param str orbit: Type of orbit (satellite only).
        :param str processing_level: Way in which raw data has been processed if any.
        :param str resolution: Pixel density of the data, provide units.
        :param str revisit: How often an AOI can expect updated data.
        :param str sensor: Name of the sensor used.
        :param str swath: How large an area the sensor captures at a given time.
        :param list(str) writers: A list of groups, or user hashes to give read access to.

        :return: JSON API representation of the product.
        :rtype: dict
        """
        for k, v in locals().items():
            if k in ["title", "description"]:
                if v is None:
                    raise TypeError("required arg `{}` not provided".format(k))
                kwargs[k] = v
        check_deprecated_kwargs(
            kwargs, {"start_time": "start_datetime", "end_time": "end_datetime"}
        )

        if add_namespace:
            check_deprecated_kwargs(locals(), {"add_namespace": None})
            product_id = self.namespace_product(product_id)

        params = None
        if set_global_permissions is True:
            params = {"set_global_permissions": "true"}

        r = self.session.put(
            "/products/{}".format(product_id), json=kwargs, params=params
        )
        return r.json()
Esempio n. 13
0
    def add_product(self,
                    product_id,
                    title,
                    description,
                    add_namespace=False,
                    **kwargs):
        """Add a product to your catalog.

        :param str product_id: (Required) A unique name for this product. In the created
            product a namespace consisting of your user id (e.g.
            "ae60fc891312ggadc94ade8062213b0063335a3c:") or your organization id (e.g.,
            "yourcompany:") will be prefixed to this, if it doesn't already have one, in
            order to make the id globally unique.
        :param str title: (Required) Official product title.
        :param str description: (Required) Information about the product,
                                why it exists, and what it provides.

        :param bool add_namespace: Add your user namespace to the product_id. *Deprecated*
        :param list(str) read: A list of groups, or user hashes to give read access to.
        :param int spectral_bands: Number of spectral bands the product has.
        :param list(str) native_bands: A list of the names of the native bands of this product
                                        (most applicable to satellite sensors).
        :param str start_datetime: ISO8601 compliant date string, indicating start of product data.
        :param str end_datetime: ISO8601 compliant date string, indicating end of product data.
        :param str notes: Any notes to relay about the product.
        :param str orbit: Type of orbit (satellite only).
        :param str processing_level: Way in which raw data has been processed if any.
        :param str resolution: Pixel density of the data, provide units.
        :param str revisit: How often an AOI can expect updated data.
        :param str sensor: Name of the sensor used.
        :param str swath: How large an area the sensor captures at a given time.
        :param list(str) writers: A list of groups, or user hashes to give read access to.

        :return: JSON API representation of the product.
        :rtype: dict
        """
        for k, v in locals().items():
            if k in ["title", "description"]:
                if v is None:
                    raise TypeError("required arg `{}` not provided".format(k))
                kwargs[k] = v
        check_deprecated_kwargs(kwargs, {
            "start_time": "start_datetime",
            "end_time": "end_datetime"
        })

        if add_namespace:
            check_deprecated_kwargs(locals(), {"add_namespace": None})
            kwargs["id"] = self.namespace_product(product_id)
        else:
            kwargs["id"] = product_id

        r = self.session.post("/products", json=kwargs)
        return r.json()
Esempio n. 14
0
    def get_band(self, product_id, name, add_namespace=False):
        """Get a band by name.

        :return: JSON API representation of the band.
        :rtype: dict
        """
        if add_namespace:
            check_deprecated_kwargs(locals(), {"add_namespace": None})
            product_id = self.namespace_product(product_id)

        r = self.session.get("/products/{}/bands/{}".format(product_id, name))
        return r.json()
Esempio n. 15
0
    def change_product(self,
                       product_id,
                       add_namespace=False,
                       set_global_permissions=False,
                       **kwargs):
        """Update a product in your catalog.

        :param str product_id: (Required) The ID of the product to change.
        :param list(str) read: A list of groups, or user hashes to give read access to.
        :param int spectral_bands: Number of spectral bands the product has.
        :param list(str) native_bands: A list of the names of the native bands of this product
                                        (most applicable to satellite sensors).

        :param bool add_namespace: Add your user namespace to the product_id. *Deprecated*
        :param bool set_global_permissions: Update permissions of all existing bands and products
                                            that belong to this product with the updated permission set
                                            specified in the `read` param. Default to false.

        :param str start_datetime: ISO8601 compliant date string, indicating start of product data.
        :param str end_datetime: ISO8601 compliant date string, indicating end of product data.
        :param str title: Official product title.
        :param str description: Information about the product,
                                why it exists, and what it provides.
        :param str notes: Any notes to relay about the product.
        :param str orbit: Type of orbit (satellite only).
        :param str processing_level: Way in which raw data has been processed if any.
        :param str resolution: Pixel density of the data, provide units.
        :param str revisit: How often an AOI can expect updated data.
        :param str sensor: Name of the sensor used.
        :param str swath: How large an area the sensor captures at a given time.
        :param list(str) writers: A list of groups, or user hashes to give read access to.

        :return: JSON API representation of the product.
        :rtype: dict
        """
        check_deprecated_kwargs(kwargs, {
            "start_time": "start_datetime",
            "end_time": "end_datetime"
        })

        if add_namespace:
            check_deprecated_kwargs(locals(), {"add_namespace": None})
            product_id = self.namespace_product(product_id)

        params = None
        if set_global_permissions is True:
            params = {"set_global_permissions": "true"}

        r = self.session.patch("/products/{}".format(product_id),
                               json=kwargs,
                               params=params)
        return r.json()
Esempio n. 16
0
    def remove_product(self, product_id, add_namespace=False, cascade=False):
        """Remove a product from the catalog.

        :param str product_id: ID of the product to remove.
        :param bool cascade: Force deletion of all the associated bands and images. BEWARE this cannot be undone.
        """
        if add_namespace:
            check_deprecated_kwargs(locals(), {"add_namespace": None})
            product_id = self.namespace_product(product_id)
        params = {"cascade": cascade}
        r = self.session.delete("/products/{}".format(product_id), params=params)
        if r.headers["content-type"] == "application/json":
            return r.json()
Esempio n. 17
0
    def get_image(self, product_id, image_id, add_namespace=False):
        """Get a single image metadata entry.

        :return: JSON API representation of the image.
        :rtype: dict
        """

        if add_namespace:
            check_deprecated_kwargs(locals(), {"add_namespace": None})
            product_id = self.namespace_product(product_id)

        r = self.session.get("/products/{}/images/{}".format(product_id, image_id))
        return r.json()
Esempio n. 18
0
    def _do_upload(self, file_ish, product_id, metadata=None, add_namespace=False):
        # kwargs are treated as metadata fields and restricted to primitives
        # for the key val pairs.
        fd = None
        if add_namespace:
            check_deprecated_kwargs(locals(), {"add_namespace": None})
            product_id = self.namespace_product(product_id)

        if metadata is None:
            metadata = {}
        metadata.setdefault("process_controls", {"upload_type": "file"})
        check_deprecated_kwargs(metadata, {"bpp": "bits_per_pixel"})

        if isinstance(file_ish, io.IOBase):
            if "b" not in file_ish.mode:
                file_ish = io.open(file_ish.name, "rb")
            fd = file_ish
        elif isinstance(file_ish, six.string_types) and os.path.exists(file_ish):
            fd = io.open(file_ish, "rb")
        else:
            return (
                1,
                file_ish,
                Exception(
                    "Could not handle file: `{}` pass a valid path or open IOBase instance".format(
                        file_ish
                    )
                ),
            )
        try:
            r = self.session.post(
                "/products/{}/images/upload/{}".format(
                    product_id,
                    metadata.pop("image_id", None) or os.path.basename(fd.name),
                ),
                json=metadata,
            )
            upload_url = r.text
            r = self._gcs_upload_service.session.put(upload_url, data=fd)
        except (ServerError, RequestException) as e:
            return 1, fd.name, e
        finally:
            fd.close()

        return 0, fd.name, ""
Esempio n. 19
0
    def change_band(self, product_id, name, add_namespace=False, **kwargs):
        """Update a data band of a product.

        :param str product_id: (Required) Product to which this band belongs.
        :param str name: Name or id of band to modify.

        .. note::
            - See :meth:`Catalog.add_band` for additional kwargs.

        :return: JSON API representation of the band.
        :rtype: dict
        """
        if add_namespace:
            check_deprecated_kwargs(locals(), {"add_namespace": None})
            product_id = self.namespace_product(product_id)
        r = self.session.patch("/products/{}/bands/{}".format(
            product_id, name),
                               json=kwargs)
        return r.json()
Esempio n. 20
0
    def add_band(self,
                 product_id,
                 name,
                 add_namespace=False,
                 srcband=None,
                 dtype=None,
                 nbits=None,
                 data_range=None,
                 type=None,
                 **kwargs):
        """Add a data band to an existing product.

        :param str product_id: (Required) Product to which this band will belong.
        :param str name: (Required) Name of this band.
        :param bool add_namespace: Add your user namespace to the product_id. *Deprecated*
        :param int jpx_layer: If data is processed to JPEG2000, which layer is the band in. Defaults to 0.
        :param int srcband: (Required) The 1-based index of the band in the jpx_layer specified.
        :param int srcfile: If the product was processed into multiple files,
                            which one is this in. Defaults to 0 (first file).
        :param str dtype: (Required) The data type used to store this band e.g Byte or Uint16 or Float32.
        :param int nbits: (Required) The number of bits of the dtype used to store this band.
        :param list(int) data_range: (Required) A list specifying the min and max values for the data in this band.
        :param str type: (Required) The data interpretation of the band. One of ['spectral', 'derived', 'mask', 'class']

        :param int nodata: Pixel value indicating no data available.
        :param list(str) read: A list of groups, or user hashes to give read access to.
                                     Defaults to the same as the parent product if not specified.
        :param str color: The color interpretation of this band.
                          One of ['Alpha', 'Black', 'Blue', 'Cyan', 'Gray', 'Green', 'Hue',
                          'Ligntness', 'Magenta', 'Palette', 'Red', 'Saturation',
                          'Undefined', 'YCbCr_Cb', 'YCbCr_Cr', 'YCbCr_Y', 'Yellow'].
                          Must be 'Alpha' if `type` is 'mask'.
                          Must be 'Palette' if `colormap_name` or `colormap` is set.
        :param str colormap_name: A named colormap to use for this band, one of
                                  ['plasma', 'magma', 'viridis', 'msw', 'inferno']
        :param list(list(str)) colormap: A custom colormap to use for this band. Takes a list of lists, where each
                                         nested list is a 4-tuple of rgba values to map pixels whose value is the index
                                         of the tuple. i.e the colormap [["100", "20", "200", "255"]] would map pixels
                                         whose value is 0 in the original band, to the rgba color vector at colormap[0].
                                         Less than 2^nbits 4-tuples may be provided, and omitted values
                                         will default map to black.

        :param str data_description: Description of band data.
        :param list(float) physical_range: If band represents a physical value e.g reflectance
                                           or radiance what are the possible range of those values.
        :param str data_unit: Units of the physical range e.g w/sr for radiance
        :param str data_unit_description: Description of the data unit.
        :param list(int) default_range: A good default scale for the band to use
                                        when rastering for display purposes.
        :param str description: Description of the band.
        :param str name_common: Standard name for band
        :param str name_vendor: What the vendor calls the band eg. B1
        :param int vendor_order: The index of the band in the vendors band tables.
                                 Useful for referencing the band to other processing
                                 properties like surface reflectance.
        :param str processing_level: Description of how the band was processed if at all.
        :param int res_factor: Scaling of this band relative to the native band resolution.
        :param int resolution: Resolution of this band.
        :param str resolution_unit: Unit of the resolution.
        :param float wavelength_center: Center position of wavelength.
        :param float wavelength_fwhm: Full width at half maximum value of the wavelength spread.
        :param float wavelength_min: Minimum wavelength this band is sensitive to.
        :param float wavelength_max: Maximum wavelength this band is sensitive to.
        :param str wavelength_unit: Units the wavelength is expressed in.
        :param list(str) writers: A list of groups, or user hashes to give read access to.

        :return: JSON API representation of the band.
        :rtype: dict
        """

        for k, v in locals().items():
            if k in [
                    "name", "data_range", "dtype", "nbits", "srcband", "type"
            ]:
                if v is None:
                    raise TypeError("required arg `{}` not provided".format(k))
                kwargs[k] = v
        if add_namespace:
            check_deprecated_kwargs(locals(), {"add_namespace": None})
            product_id = self.namespace_product(product_id)
        check_deprecated_kwargs(kwargs, {"id": "name"})

        r = self.session.post("/products/{}/bands".format(product_id),
                              json=kwargs)
        return r.json()
Esempio n. 21
0
 def remove_image(self, product_id, image_id, add_namespace=False):
     if add_namespace:
         check_deprecated_kwargs(locals(), {"add_namespace": None})
         product_id = self.namespace_product(product_id)
     self.session.delete("/products/{}/images/{}".format(
         product_id, image_id))
Esempio n. 22
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,
                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.
        :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 expr 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 resolution, bounds, and srs.

        Example usage::

            >>> 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',
                      '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:
            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

        r = self.session.post("/summary", json=kwargs)
        return DotDict(r.json())
Esempio n. 23
0
    def add_image(self, product_id, image_id, add_namespace=False, **kwargs):
        """Add an image metadata entry to a product.

        :param str product_id: (Required) Product to which this image belongs.
        :param str image_id: (Required) New image's id = <product_id>:<image_id>.
        :param bool add_namespace: Add your user namespace to the product_id. *Deprecated*
        :param list(str) read: A list of groups, or user hashes to give read access to.
                                     Defaults to the same as the parent product if not specified.
        :param int absolute_orbit: Orbit number since mission start.
        :param str acquired: Date the imagery was acquired
        :param str archived: Date the imagery was archived.
        :param float area: Surface area the image covers
        :param float azimuth_angle:
        :param float azimuth_angle_1:
        :param list(float) bits_per_pixel: Average bits of data per pixel per band.
        :param float bright_fraction: Fraction of the image that has reflectance greater than .4 in the blue band.
        :param str bucket: Name of Google Cloud Bucket. Must be public bucket or Descartes Labs user bucket.
        :param str catalog_id:
        :param float cirrus_fraction: Fraction of pixel which are distorted by cirrus clouds.
        :param float cloud_fraction: Fraction of pixels which are obscured by clouds.
        :param float cloud_fraction_0: Fraction of pixels which are obscured by clouds.
        :param str cs_code: Spatial coordinate system code eg. `EPSG:4326`
        :param datastrip_id: ID of the data strip this image was taken in.
        :param float degraded_fraction_0:
        :param str descartes_version:
        :param str directory: Subdirectory location.
        :param float duration: duration of the scan in seconds
        :param int duration_days:
        :param float earth_sun_distance: Earth sun distance at time of image capture.
        :param list(str) files: Names of the files this image is stored in.
        :param list(str) file_md5s: File integrity checksums.
        :param list(int) file_sizes: Number of bytes of each file
        :param float fill_fraction: Fraction of this image which has data.
        :param float geolocation_accuracy:
        :param str|dict geometry: GeoJSON representation of the image coverage.
        :param float geotrans: Geographic Translator values.
        :param float gpt_time:
        :param str identifier: Vendor scene identifier.
        :param int ifg_tdelta_days:
        :param float incidence_angle: Sensor incidence angle.
        :param str pass: On which pass was this image taken.
        :param str processed: Date which this image was processed.
        :param str proj4: proj.4 transformation parameters
        :param str projcs: Projection coordinate system.
        :param str published: Date the image was published.
        :param str radiometric_version:
        :param list(int) raster_size: Dimensions of image in pixels in (width, height).
        :param list(float) reflectance_scale: Scale factors converting TOA radiances to TOA reflectances
        :param list(float) reflectance_scale_1:
        :param int relative_orbit: Orbit number in revisit cycle.
        :param float roll_angle:
        :param str safe_id: Standard Archive Format for Europe.
        :param str sat_id: Satellite identifier.
        :param float scan_gap_interpolation:
        :param float solar_azimuth_angle:
        :param float solar_azimuth_angle_0:
        :param float solar_azimuth_angle_1:
        :param float solar_elevation_angle:
        :param float solar_elevation_angle_0:
        :param float solar_elevation_angle_1:
        :param str tile_id:
        :param float view_angle:
        :param float view_angle_1:
        :param list(str) writers: A list of groups, or user hashes to give read access to.
        :param dict extra_properties: User defined custom properties for this image.
            Only 10 keys are allowed. The dict can only map strings to primitive types (str -> str|float|int).

        :return: JSON API representation of the image.
        :rtype: dict
        """
        check_deprecated_kwargs(kwargs, {
            "bpp": "bits_per_pixel",
            "key": "image_id"
        })
        if add_namespace:
            check_deprecated_kwargs(locals(), {"add_namespace": None})
            product_id = self.namespace_product(product_id)
        kwargs["id"] = image_id
        r = self.session.post("/products/{}/images".format(product_id),
                              json=kwargs)
        return r.json()
Esempio n. 24
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,
                     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.
        :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 expr 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 resolution, bounds, and srs.
        :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.


        """
        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:
            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 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)
Esempio n. 25
0
    def _query(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,
               q=None,
               limit=100,
               fields=None,
               dltile=None,
               sort_field=None,
               sort_order="asc",
               randomize=None,
               continuation_token=None,
               **kwargs):
        """
        Execute a metadata query for up to 10,000 items.

        Use :py:func:`search` or :py:func:`features` instead, which batch searches into smaller requests
        and handle paging for you.
        """
        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:
            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 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)