def test_as_json_string(self): d = {'a': 'b'} truth = json.dumps(d) self.assertEqual(as_json_string(d), truth) s = '{"a": "b"}' self.assertEqual(as_json_string(s), truth) self.assertEqual(as_json_string(None), None)
def dltiles_from_shape(self, resolution, tilesize, pad, shape): """ Return a feature collection of DLTile GeoJSONs that intersect a GeoJSON Geometry `shape`. :param float resolution: Resolution of DLTile :param int tilesize: Number of valid pixels per DLTile :param int pad: Number of ghost pixels per DLTile :param str shape: A GeoJSON geometry specifying a shape over which to intersect DLTiles. :return: GeoJSON FeatureCollection of intersecting DLTile geometries. Example:: >>> import descarteslabs as dl >>> from pprint import pprint >>> iowa = dl.places.shape("north-america_united-states_iowa") >>> tiles = dl.raster.dltiles_from_shape(30.0, 2048, 16, iowa) >>> pprint(tiles['features'][0]) {'geometry': {'coordinates': [[[-96.81264975325391, 41.04520331997488], [-96.07101667769165, 41.02873098011615], [-96.04576296033328, 41.590072611375206], [-96.79377566762062, 41.606871549447824], [-96.81264975325391, 41.04520331997488]]], 'type': 'Polygon'}, 'properties': {'cs_code': 'EPSG:32614', 'key': '2048:16:30.0:14:3:74', 'outputBounds': [683840.0, 4546080.0, 746240.0, 4608480.0], 'pad': 16, 'resolution': 30.0, 'ti': 3, 'tilesize': 2048, 'tj': 74, 'zone': 14}, 'type': 'Feature'} """ shape = as_json_string(shape) params = { 'resolution': resolution, 'tilesize': tilesize, 'pad': pad, 'shape': shape, } r = self.session.post('%s/dlkeys/from_shape' % (self.url), json=params, timeout=self.TIMEOUT) if r.status_code != 200: raise RuntimeError("%s: %s" % (r.status_code, r.text)) return r.json()
def ndarray( self, inputs, bands=None, scales=None, data_type=None, srs=None, resolution=None, dimensions=None, cutline=None, place=None, bounds=None, bounds_srs=None, align_pixels=False, resampler=None, order='image', ): """Retrieve a raster as a NumPy array. :param inputs: List of :class:`Metadata` identifiers. :param bands: List of requested bands. :param scales: List of tuples specifying the scaling to be applied to each band. If no scaling is desired for a band, use ``None`` where appropriate. If a tuple contains four elements, the last two will be used as the output range. For example, ``(0, 10000, 0, 128)`` would scale the source values 0-10000 to be returned as 0-128 in the output. :param str data_type: Output data type (`Byte`, `UInt8`, `UInt16`, `Float32`, etc). :param str srs: Output spatial reference system definition understood by GDAL. :param float resolution: Desired resolution in output SRS units. Incompatible with `dimensions` :param tuple dimensions: Desired output (width, height) in pixels. Incompatible with `resolution` :param str cutline: A GeoJSON feature or geometry to be used as a cutline. :param str place: A slug identifier to be used as a cutline. :param tuple bounds: ``(min_x, min_y, max_x, max_y)`` in target SRS. :param str bounds_srs: Override the coordinate system in which bounds are expressed. :param bool align_pixels: Align pixels to the target coordinate system. :param str resampler: Resampling algorithm to be used during warping (``near``, ``bilinear``, ``cubic``, ``cubicsplice``, ``lanczos``, ``average``, ``mode``, ``max``, ``min``, ``med``, ``q1``, ``q3``). :param str order: Order of the returned array. `image` returns arrays as ``(row, column, band)`` while `gdal` returns arrays as ``(band, row, column)``. """ cutline = as_json_string(cutline) if place is not None: places = Places() places.auth = self.auth shape = places.shape(place, geom='low') cutline = json.dumps(shape['geometry']) params = { 'keys': inputs, 'bands': bands, 'scales': scales, 'ot': data_type, 'srs': srs, 'resolution': resolution, 'shape': cutline, 'outputBounds': bounds, 'outputBoundsSRS': bounds_srs, 'outsize': dimensions, 'targetAlignedPixels': align_pixels, 'resampleAlg': resampler, } r = self.session.post('%s/npz' % (self.url), json=params, timeout=self.TIMEOUT) io = BytesIO(r.content) npz = np.load(io) array = npz['data'] metadata = json.loads(npz['metadata'].tostring().decode('utf-8')) if len(array.shape) > 2: if order == 'image': return array.transpose((1, 2, 0)), metadata elif order == 'gdal': return array, metadata else: return array, metadata
def raster( self, inputs, bands=None, scales=None, data_type=None, output_format='GTiff', srs=None, dimensions=None, resolution=None, bounds=None, bounds_srs=None, cutline=None, place=None, align_pixels=False, resampler=None, ): """Given a list of :class:`Metadata <descarteslabs.services.Metadata>` identifiers, retrieve a translated and warped mosaic. :param inputs: List of :class:`Metadata` identifiers. :param bands: List of requested bands. :param scales: List of tuples specifying the scaling to be applied to each band. If no scaling is desired for a band, use ``None`` where appropriate. If a tuple contains four elements, the last two will be used as the output range. For example, ``(0, 10000, 0, 128)`` would scale the source values 0-10000 to be returned as 0-128 in the output. :param str output_format: Output format (`GTiff`, `PNG`, ...). :param str data_type: Output data type (`Byte`, `UInt8`, `UInt16`, `Float32`, etc). :param str srs: Output spatial reference system definition understood by GDAL. :param float resolution: Desired resolution in output SRS units. Incompatible with `dimensions` :param tuple dimensions: Desired output (width, height) in pixels. Incompatible with `resolution` :param str cutline: A GeoJSON feature or geometry to be used as a cutline. :param str place: A slug identifier to be used as a cutline. :param tuple bounds: ``(min_x, min_y, max_x, max_y)`` in target SRS. :param str bounds_srs: Override the coordinate system in which bounds are expressed. :param bool align_pixels: Align pixels to the target coordinate system. :param str resampler: Resampling algorithm to be used during warping (``near``, ``bilinear``, ``cubic``, ``cubicsplice``, ``lanczos``, ``average``, ``mode``, ``max``, ``min``, ``med``, ``q1``, ``q3``). """ cutline = as_json_string(cutline) if place: places = Places() places.auth = self.auth shape = places.shape(place, geom='low') cutline = json.dumps(shape['geometry']) params = { 'keys': inputs, 'bands': bands, 'scales': scales, 'ot': data_type, 'of': output_format, 'srs': srs, 'resolution': resolution, 'shape': cutline, 'outputBounds': bounds, 'outputBoundsSRS': bounds_srs, 'outsize': dimensions, 'targetAlignedPixels': align_pixels, 'resampleAlg': resampler, } r = self.session.post('%s/raster' % (self.url), json=params, timeout=self.TIMEOUT) if r.status_code != 200: raise RuntimeError("%s: %s" % (r.status_code, r.text)) json_resp = r.json() # Decode base64 for k in json_resp['files'].keys(): json_resp['files'][k] = base64.b64decode(json_resp['files'][k]) return json_resp
def ndarray( self, inputs, bands=None, scales=None, data_type=None, srs=None, resolution=None, dimensions=None, cutline=None, place=None, bounds=None, bounds_srs=None, align_pixels=False, resampler=None, order='image', ): """Retrieve a raster as a NumPy array. See :meth:`raster` for more information. :param str order: Order of the returned array. `image` returns arrays as ``(row, column, band)`` while `gdal` returns arrays as ``(band, row, column)``. """ cutline = as_json_string(cutline) if place is not None: places = Places() places.auth = self.auth shape = places.shape(place, geom='low') cutline = json.dumps(shape['geometry']) params = { 'keys': inputs, 'bands': bands, 'scales': scales, 'ot': data_type, 'srs': srs, 'resolution': resolution, 'shape': cutline, 'outputBounds': bounds, 'outputBoundsSRS': bounds_srs, 'outsize': dimensions, 'targetAlignedPixels': align_pixels, 'resampleAlg': resampler, } r = self.session.post('%s/npz' % (self.url), json=params, timeout=self.TIMEOUT) io = BytesIO(r.content) npz = np.load(io) array = npz['data'] metadata = json.loads(npz['metadata'].tostring().decode('utf-8')) if len(array.shape) > 2: if order == 'image': return array.transpose((1, 2, 0)), metadata elif order == 'gdal': return array, metadata else: return array, metadata
def raster( self, inputs, bands=None, scales=None, data_type=None, output_format='GTiff', srs=None, dimensions=None, resolution=None, bounds=None, bounds_srs=None, cutline=None, place=None, align_pixels=False, resampler=None, dltile=None, save=False, outfile_basename=None, **pass_through_params ): """Given a list of :class:`Metadata <descarteslabs.services.Metadata>` identifiers, retrieve a translated and warped mosaic. :param inputs: List of :class:`Metadata` identifiers. :param bands: List of requested bands. If the last item in the list is an alpha band (with data range `[0, 1]`) it affects rastering of all other bands: When rastering multiple images, they are combined image-by-image only where each respective image's alpha band is `1` (pixels where the alpha band is not `1` are "transparent" in the overlap between images). If a pixel is fully masked considering all combined alpha bands it will be `0` in all non-alpha bands. :param scales: List of tuples specifying the scaling to be applied to each band. If no scaling is desired for a band, use ``None`` where appropriate. If a tuple contains four elements, the last two will be used as the output range. For example, ``(0, 10000, 0, 128)`` would scale the source values 0-10000 to be returned as 0-128 in the output. :param str output_format: Output format (`GTiff`, `PNG`, ...). :param str data_type: Output data type (`Byte`, `UInt8`, `UInt16`, `Float32`, etc). :param str srs: Output spatial reference system definition understood by GDAL. :param float resolution: Desired resolution in output SRS units. Incompatible with `dimensions` :param tuple dimensions: Desired output (width, height) in pixels. Incompatible with `resolution` :param str cutline: A GeoJSON feature or geometry to be used as a cutline. :param str place: A slug identifier to be used as a cutline. :param tuple bounds: ``(min_x, min_y, max_x, max_y)`` in target SRS. :param str bounds_srs: Override the coordinate system in which bounds are expressed. :param bool align_pixels: Align pixels to the target coordinate system. :param str resampler: Resampling algorithm to be used during warping (``near``, ``bilinear``, ``cubic``, ``cubicsplice``, ``lanczos``, ``average``, ``mode``, ``max``, ``min``, ``med``, ``q1``, ``q3``). :param str dltile: a dltile key used to specify the resolution, bounds, and srs. :param bool save: Write resulting files to disk. Default: False :param str outfile_basename: If 'save' is True, override default filename using this string as a base. """ cutline = as_json_string(cutline) if place: places = Places() places.auth = self.auth shape = places.shape(place, geom='low') cutline = json.dumps(shape['geometry']) params = { 'keys': inputs, 'bands': bands, 'scales': scales, 'ot': data_type, 'of': output_format, 'srs': srs, 'resolution': resolution, 'shape': cutline, 'outputBounds': bounds, 'outputBoundsSRS': bounds_srs, 'outsize': dimensions, 'targetAlignedPixels': align_pixels, 'resampleAlg': resampler, } params.update(pass_through_params) if dltile is not None: if isinstance(dltile, dict): params['dltile'] = dltile['properties']['key'] else: params['dltile'] = dltile r = self.session.post('/raster', json=params) json_resp = r.json() # Decode base64 for k in list(json_resp['files'].keys()): if outfile_basename: outfilename = "{}.{}".format( outfile_basename, ".".join(os.path.basename(k).split(".")[1:]) ) else: outfilename = k json_resp['files'][outfilename] = base64.b64decode( json_resp['files'].pop(k) ) if save: for filename, data in six.iteritems(json_resp['files']): with open(filename, "wb") as f: f.write(data) return json_resp
def ndarray(self, inputs, bands=None, scales=None, data_type=None, srs=None, resolution=None, dimensions=None, cutline=None, place=None, bounds=None, bounds_srs=None, align_pixels=False, resampler=None, order='image', dltile=None, **pass_through_params): """Retrieve a raster as a NumPy array. :param inputs: List of :class:`Metadata` identifiers. :param bands: List of requested bands. If the last item in the list is an alpha band (with data range `[0, 1]`) it affects rastering of all other bands: When rastering multiple images, they are combined image-by-image only where each respective image's alpha band is `1` (pixels where the alpha band is not `1` are "transparent" in the overlap between images). If a pixel is fully masked considering all combined alpha bands it will be `0` in all non-alpha bands. :param scales: List of tuples specifying the scaling to be applied to each band. If no scaling is desired for a band, use ``None`` where appropriate. If a tuple contains four elements, the last two will be used as the output range. For example, ``(0, 10000, 0, 128)`` would scale the source values 0-10000 to be returned as 0-128 in the output. :param str data_type: Output data type (`Byte`, `UInt8`, `UInt16`, `Float32`, etc). :param str srs: Output spatial reference system definition understood by GDAL. :param float resolution: Desired resolution in output SRS units. Incompatible with `dimensions` :param tuple dimensions: Desired output (width, height) in pixels. Incompatible with `resolution` :param str cutline: A GeoJSON feature or geometry to be used as a cutline. :param str place: A slug identifier to be used as a cutline. :param tuple bounds: ``(min_x, min_y, max_x, max_y)`` in target SRS. :param str bounds_srs: Override the coordinate system in which bounds are expressed. :param bool align_pixels: Align pixels to the target coordinate system. :param str resampler: Resampling algorithm to be used during warping (``near``, ``bilinear``, ``cubic``, ``cubicsplice``, ``lanczos``, ``average``, ``mode``, ``max``, ``min``, ``med``, ``q1``, ``q3``). :param str order: Order of the returned array. `image` returns arrays as ``(row, column, band)`` while `gdal` returns arrays as ``(band, row, column)``. :param str dltile: a dltile key used to specify the resolution, bounds, and srs. """ cutline = as_json_string(cutline) if place is not None: places = Places() places.auth = self.auth shape = places.shape(place, geom='low') cutline = json.dumps(shape['geometry']) params = { 'keys': inputs, 'bands': bands, 'scales': scales, 'ot': data_type, 'srs': srs, 'resolution': resolution, 'shape': cutline, 'outputBounds': bounds, 'outputBoundsSRS': bounds_srs, 'outsize': dimensions, 'targetAlignedPixels': align_pixels, 'resampleAlg': resampler, } params.update(pass_through_params) if dltile is not None: if isinstance(dltile, dict): params['dltile'] = dltile['properties']['key'] else: params['dltile'] = dltile can_blosc = not isinstance(blosc, ThirdParty) if can_blosc: params['of'] = 'blosc' else: params['of'] = 'npz' r = self.session.post('/npz', json=params, stream=True) if can_blosc: metadata = json.loads(r.raw.readline().decode('utf-8').strip()) array_meta = json.loads(r.raw.readline().decode('utf-8').strip()) array = read_blosc_array(array_meta, r.raw) else: npz = np.load(BytesIO(r.content)) array = npz['data'] metadata = json.loads(npz['metadata'].tostring().decode('utf-8')) if len(array.shape) > 2: if order == 'image': return array.transpose((1, 2, 0)), metadata elif order == 'gdal': return array, metadata else: return array, metadata
def raster(self, inputs, bands=None, scales=None, data_type=None, output_format='GTiff', srs=None, dimensions=None, resolution=None, bounds=None, bounds_srs=None, cutline=None, place=None, align_pixels=False, resampler=None, dltile=None, save=False, outfile_basename=None, **pass_through_params): """Given a list of :class:`Metadata <descarteslabs.services.Metadata>` identifiers, retrieve a translated and warped mosaic. :param inputs: List of :class:`Metadata` identifiers. :param bands: List of requested bands. If the last item in the list is an alpha band (with data range `[0, 1]`) it affects rastering of all other bands: When rastering multiple images, they are combined image-by-image only where each respective image's alpha band is `1` (pixels where the alpha band is not `1` are "transparent" in the overlap between images). If a pixel is fully masked considering all combined alpha bands it will be `0` in all non-alpha bands. :param scales: List of tuples specifying the scaling to be applied to each band. A tuple has 4 elements in the order ``(src_min, src_max, out_min, out_max)``, meaning values in the source range ``src_min`` to ``src_max`` will be scaled to the output range ``out_min`` to ``out_max``. A tuple with 2 elements ``(src_min, src_max)`` is also allowed, in which case the output range defaults to ``(0, 255)`` (a useful default for the common output type ``Byte``). If no scaling is desired for a band, use ``None``. This tuple format and behaviour is identical to GDAL's scales during translation. Example argument: ``[(0, 10000, 0, 127), None, (0, 10000)]`` - the first band will have source values 0-10000 scaled to 0-127, the second band will not be scaled, the third band will have 0-10000 scaled to 0-255. :param str output_format: Output format (one of ``GTiff``, ``PNG``, ``JPEG``). :param str data_type: Output data type (one of ``Byte``, ``UInt16``, ``Int16``, ``UInt32``, ``Int32``, ``Float32``, ``Float64``). :param str srs: Output spatial reference system definition understood by GDAL. :param float resolution: Desired resolution in output SRS units. Incompatible with `dimensions` :param tuple dimensions: Desired output (width, height) in pixels. Incompatible with `resolution` :param str cutline: A GeoJSON feature or geometry to be used as a cutline. :param str place: A slug identifier to be used as a cutline. :param tuple bounds: ``(min_x, min_y, max_x, max_y)`` in target SRS. :param str bounds_srs: Override the coordinate system in which bounds are expressed. :param bool align_pixels: Align pixels to the target coordinate system. :param str resampler: Resampling algorithm to be used during warping (``near``, ``bilinear``, ``cubic``, ``cubicsplice``, ``lanczos``, ``average``, ``mode``, ``max``, ``min``, ``med``, ``q1``, ``q3``). :param str dltile: a dltile key used to specify the resolution, bounds, and srs. :param bool save: Write resulting files to disk. Default: False :param str outfile_basename: If 'save' is True, override default filename using this string as a base. """ cutline = as_json_string(cutline) if place: places = Places() places.auth = self.auth shape = places.shape(place, geom='low') cutline = json.dumps(shape['geometry']) params = { 'keys': inputs, 'bands': bands, 'scales': scales, 'ot': data_type, 'of': output_format, 'srs': srs, 'resolution': resolution, 'shape': cutline, 'outputBounds': bounds, 'outputBoundsSRS': bounds_srs, 'outsize': dimensions, 'targetAlignedPixels': align_pixels, 'resampleAlg': resampler, } params.update(pass_through_params) if dltile is not None: if isinstance(dltile, dict): params['dltile'] = dltile['properties']['key'] else: params['dltile'] = dltile r = self.session.post('/raster', json=params) raw = BytesIO(r.content) json_resp = json.loads(raw.readline().decode('utf-8').strip()) num_files = json_resp['files'] json_resp['files'] = {} for _ in range(num_files): file_meta = json.loads(raw.readline().decode('utf-8').strip()) fn = file_meta['name'] data = raw.read(file_meta['length']) if outfile_basename: outfilename = "{}.{}".format( outfile_basename, ".".join(os.path.basename(fn).split(".")[1:])) else: outfilename = fn json_resp['files'][outfilename] = data if save: for filename, data in six.iteritems(json_resp['files']): with open(filename, "wb") as f: f.write(data) return json_resp