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()
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, ''
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()
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]
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()
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()
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()
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()
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())
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
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
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()
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()
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()
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()
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()
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()
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, ""
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()
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()
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))
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())
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()
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)
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)