def preview(image, **kwargs): ''' Show a slippy map preview of the image. Requires iPython. Args: image (image): image object to display zoom (int): zoom level to intialize the map, default is 16 center (list): center coordinates to initialize the map, defaults to center of image bands (list): bands of image to display, defaults to the image's default RGB bands ''' try: from IPython.display import Javascript, HTML, display from gbdxtools.rda.interface import RDA from gbdxtools import Interface gbdx = Interface() except: print("IPython is required to produce maps.") return zoom = kwargs.get("zoom", 16) bands = kwargs.get("bands") if bands is None: bands = image._rgb_bands wgs84_bounds = kwargs.get( "bounds", list(loads(image.metadata["image"]["imageBoundsWGS84"]).bounds)) center = kwargs.get("center", list(shape(image).centroid.bounds[0:2])) if image.proj != 'EPSG:4326': code = image.proj.split(':')[1] conn = gbdx.gbdx_connection proj_info = conn.get( 'https://ughlicoordinates.geobigdata.io/ughli/v1/projinfo/{}'. format(code)).json() tfm = partial(pyproj.transform, pyproj.Proj(init='EPSG:4326'), pyproj.Proj(init=image.proj)) bounds = list(ops.transform(tfm, box(*wgs84_bounds)).bounds) else: proj_info = {} bounds = wgs84_bounds rda = RDA() dra = rda.HistogramDRA(image) image = dra.aoi(bbox=image.bounds) graph_id = image.rda_id node_id = image.rda.graph()['nodes'][0]['id'] map_id = "map_{}".format(str(int(time.time()))) scales = ','.join(['1'] * len(bands)) offsets = ','.join(['0'] * len(bands)) display( HTML( Template(''' <div id="$map_id"/> <link href='https://openlayers.org/en/v4.6.4/css/ol.css' rel='stylesheet' /> <script src="https://cdn.polyfill.io/v2/polyfill.min.js?features=requestAnimationFrame,Element.prototype.classList,URL"></script> <style>body{margin:0;padding:0;}#$map_id{position:relative;top:0;bottom:0;width:100%;height:400px;}</style> <style></style> ''').substitute({"map_id": map_id}))) js = Template(""" require.config({ paths: { oljs: 'https://cdnjs.cloudflare.com/ajax/libs/openlayers/4.6.4/ol', proj4: 'https://cdnjs.cloudflare.com/ajax/libs/proj4js/2.4.4/proj4' } }); require(['oljs', 'proj4'], function(oljs, proj4) { oljs.proj.setProj4(proj4) var md = $md; var georef = $georef; var graphId = '$graphId'; var nodeId = '$nodeId'; var extents = $bounds; var x1 = md.minTileX * md.tileXSize; var y1 = ((md.minTileY + md.numYTiles) * md.tileYSize + md.tileYSize); var x2 = ((md.minTileX + md.numXTiles) * md.tileXSize + md.tileXSize); var y2 = md.minTileY * md.tileYSize; var tileLayerResolutions = [georef.scaleX]; var url = '$url' + '/tile/'; url += graphId + '/' + nodeId; url += "/{x}/{y}.png?token=$token&display_bands=$bands&display_scales=$scales&display_offsets=$offsets"; var proj = '$proj'; var projInfo = $projInfo; if ( proj !== 'EPSG:4326' ) { var proj4def = projInfo["proj4"]; proj4.defs(proj, proj4def); var area = projInfo["area_of_use"]; var bbox = [area["area_west_bound_lon"], area["area_south_bound_lat"], area["area_east_bound_lon"], area["area_north_bound_lat"]] var projection = oljs.proj.get(proj); var fromLonLat = oljs.proj.getTransform('EPSG:4326', projection); var extent = oljs.extent.applyTransform( [bbox[0], bbox[1], bbox[2], bbox[3]], fromLonLat); projection.setExtent(extent); } else { var projection = oljs.proj.get(proj); } var rda = new oljs.layer.Tile({ title: 'RDA', opacity: 1, extent: extents, source: new oljs.source.TileImage({ crossOrigin: null, projection: projection, extent: extents, tileGrid: new oljs.tilegrid.TileGrid({ extent: extents, origin: [extents[0], extents[3]], resolutions: tileLayerResolutions, tileSize: [md.tileXSize, md.tileYSize], }), tileUrlFunction: function (coordinate) { if (coordinate === null) return undefined; const x = coordinate[1] + md.minTileX; const y = -(coordinate[2] + 1 - md.minTileY); if (x < md.minTileX || x > md.maxTileX) return undefined; if (y < md.minTileY || y > md.maxTileY) return undefined; return url.replace('{x}', x).replace('{y}', y); } }) }); var map = new oljs.Map({ layers: [ rda ], target: '$map_id', view: new oljs.View({ projection: projection, center: $center, zoom: $zoom }) }); }); """).substitute({ "map_id": map_id, "proj": image.proj, "projInfo": json.dumps(proj_info), "graphId": graph_id, "bounds": bounds, "bands": ",".join(map(str, bands)), "nodeId": node_id, "md": json.dumps(image.metadata["image"]), "georef": json.dumps(image.metadata["georef"]), "center": center, "zoom": zoom, "token": gbdx.gbdx_connection.access_token, "scales": scales, "offsets": offsets, "url": VIRTUAL_RDA_URL }) display(Javascript(js))
def to_geotiff(arr, path='./output.tif', proj=None, spec=None, bands=None, **kwargs): ''' Write out a geotiff file of the image Args: path (str): path to write the geotiff file to, default is ./output.tif proj (str): EPSG string of projection to reproject to spec (str): if set to 'rgb', write out color-balanced 8-bit RGB tif bands (list): list of bands to export. If spec='rgb' will default to RGB bands Returns: str: path the geotiff was written to''' assert has_rasterio, "To create geotiff images please install rasterio" try: img_md = arr.rda.metadata["image"] x_size = img_md["tileXSize"] y_size = img_md["tileYSize"] except (AttributeError, KeyError): x_size = kwargs.get("chunk_size", 256) y_size = kwargs.get("chunk_size", 256) try: tfm = kwargs['transform'] if 'transform' in kwargs else arr.affine except: tfm = None dtype = arr.dtype.name if arr.dtype.name != 'int8' else 'uint8' if spec is not None and spec.lower() == 'rgb': if bands is None: bands = arr._rgb_bands # skip if already DRA'ed if not arr.options.get('dra'): # add the RDA HistogramDRA op to get a RGB 8-bit image from gbdxtools.rda.interface import RDA rda = RDA() dra = rda.HistogramDRA(arr) # Reset the bounds and select the bands on the new Dask arr = dra.aoi(bbox=arr.bounds) arr = arr[bands,...].astype(np.uint8) dtype = 'uint8' else: if bands is not None: arr = arr[bands,...] meta = { 'width': arr.shape[2], 'height': arr.shape[1], 'count': arr.shape[0], 'dtype': dtype, 'driver': 'GTiff', 'transform': tfm } if proj is not None: meta["crs"] = {'init': proj} if "tiled" in kwargs and kwargs["tiled"]: meta.update(blockxsize=x_size, blockysize=y_size, tiled="yes") with rasterio.open(path, "w", **meta) as dst: writer = rio_writer(dst) result = store(arr, writer, compute=False) result.compute(scheduler=threaded_get) return path