def place_legend(datadir, document): """Place the ShakeMap intensity legend in the upper left corner of the viewer's map. Args: datadir (str): Path to data directory where output KMZ will be written. document (Element): LXML KML Document element. Returns: str: Path to output intensity legend file. """ icon = skml.Icon(href=LEGEND) overlayxy = skml.OverlayXY(x=0, y=90, xunits='pixels', yunits='pixels') screenxy = skml.ScreenXY(x=5, y=1, xunits='pixels', yunits='fraction') size = skml.Size(x=0, y=0, xunits='pixels', yunits='pixels') document.newscreenoverlay(name='Intensity Legend', icon=icon, overlayxy=overlayxy, screenxy=screenxy, size=size) # we need to find the legend file and copy it to # the output directory this_dir, _ = os.path.split(__file__) data_path = os.path.join(this_dir, '..', 'data', 'mapping') legend_file = os.path.join(data_path, LEGEND) legdest = os.path.join(datadir, LEGEND) shutil.copyfile(legend_file, legdest) return legdest
def _scalar2kmz(self, d, var, tndx, out_path, cleanup=True): """ Postprocess a single raster variable ``fa`` and store result in out_path. :param d: the open netCDF file :param var: the variable name :param tndx: the temporal index of the grid to store :param out_path: the path to the KMZ output :param cleanup: if true, delete png files :return: the path to the generated KMZ """ # construct kml file doc = kml.Kml(name=var) # generate the png files raster_path, cb_path, corner_coords = self._scalar2png( d, var, tndx, out_path) # add colorbar to KMZ if cb_path is not None: cbo = doc.newscreenoverlay(name='colorbar') cbo.overlayxy = kml.OverlayXY(x=0, y=1, xunits=kml.Units.fraction, yunits=kml.Units.fraction) cbo.screenxy = kml.ScreenXY(x=0.02, y=0.95, xunits=kml.Units.fraction, yunits=kml.Units.fraction) cbo.size = kml.Size(x=150, y=300, xunits=kml.Units.pixel, yunits=kml.Units.pixel) cbo.color = kml.Color.rgb(255, 255, 255, a=150) cbo.visibility = 1 #doc.addfile(cb_path) cbo.icon.href = cb_path # add ground overlay ground = doc.newgroundoverlay(name=var, color='80ffffff') ground.gxlatlonquad.coords = corner_coords #doc.addfile(raster_path) ground.icon.href = raster_path # build output file kmz_path = out_path + ".kmz" doc.savekmz(kmz_path) # cleanup if cleanup: os.remove(raster_path) if cb_path is not None: os.remove(cb_path) return kmz_path, raster_path, cb_path, corner_coords
def create_kmz(maplayer, outfile, mask=None, levels=None, colorlist=None): """ Create kmz files of models Args: maplayer (dict): Dictionary of one model result formatted like: .. code-block:: python { 'grid': mapio grid2D object, 'label': 'label for colorbar and top line of subtitle', 'type': 'output or input to model', 'description': 'description for subtitle' } outfile (str): File extension mask (float): make all cells below this value transparent levels (array): list of bin edges for each color, must be same length colorlist (array): list of colors for each bin, should be length one less than levels Returns: kmz file """ # Figure out lims if levels is None: levels = DFBINS if colorlist is None: colorlist = DFCOLORS if len(levels)-1 != len(colorlist): raise Exception('len(levels) must be one longer than len(colorlist)') # Make place to put temporary files temploc = tempfile.TemporaryDirectory() # Figure out file names name, ext = os.path.splitext(outfile) basename = os.path.basename(name) if ext != '.kmz': ext = '.kmz' filename = '%s%s' % (name, ext) mapfile = os.path.join(temploc.name, '%s.tiff' % basename) legshort = '%s_legend.png' % basename legfile = os.path.join(temploc.name, legshort) # Make colored geotiff out = make_rgba(maplayer['grid'], mask=mask, levels=levels, colorlist=colorlist) rgba_img, extent, lmin, lmax, cmap = out # Save as a tiff plt.imsave(mapfile, rgba_img, vmin=lmin, vmax=lmax, cmap=cmap) # Start creating kmz L = simplekml.Kml() # Set zoom window doc = L.document # have to put lookat in root document directory doc.altitudemode = simplekml.AltitudeMode.relativetoground boundaries1 = get_zoomextent(maplayer['grid']) doc.lookat.latitude = np.mean([boundaries1['ymin'], boundaries1['ymax']]) doc.lookat.longitude = np.mean([boundaries1['xmax'], boundaries1['xmin']]) doc.lookat.altitude = 0. doc.lookat.range = (boundaries1['ymax']-boundaries1['ymin']) * 111. * 1000. # dist in m from point doc.description = 'USGS near-real-time earthquake-triggered %s model for \ event id %s' % (maplayer['description']['parameters'] \ ['modeltype'], maplayer['description']['event_id']) prob = L.newgroundoverlay(name=maplayer['label']) prob.icon.href = 'files/%s.tiff' % basename prob.latlonbox.north = extent[3] prob.latlonbox.south = extent[2] prob.latlonbox.east = extent[1] prob.latlonbox.west = extent[0] L.addfile(mapfile) # Add legend and USGS icon as screen overlays # Make legend make_legend(levels, colorlist, filename=legfile, title=maplayer['label']) size1 = simplekml.Size(x=0.3, xunits=simplekml.Units.fraction) leg = L.newscreenoverlay(name='Legend', size=size1) leg.icon.href = 'files/%s' % legshort leg.screenxy = simplekml.ScreenXY(x=0.2, y=0.05, xunits=simplekml.Units.fraction, yunits=simplekml.Units.fraction) L.addfile(legfile) size2 = simplekml.Size(x=0.15, xunits=simplekml.Units.fraction) icon = L.newscreenoverlay(name='USGS', size=size2) icon.icon.href = 'files/USGS_ID_white.png' icon.screenxy = simplekml.ScreenXY(x=0.8, y=0.95, xunits=simplekml.Units.fraction, yunits=simplekml.Units.fraction) L.addfile(os.path.join(os.path.dirname(os.path.abspath(__file__)), os.pardir, 'content', 'USGS_ID_white.png')) L.savekmz(filename) return filename
def make_kmz(job_id, steps, mode, only_vars): """ Create KMZ file from visualization stored in wrfxweb. :param job_id: string, the name of job directory :param steps: string '1,1,1,3' takes every 3rd frame in domain 4, etc. Default: all 1 :param mode: string, 'inc', ' to include image files (default), 'ref' to use links only :param only_var: list of strings variables to include or None to include all """ logging.info('make_kmz: job_id=%s' % job_id) job_path = osp.join(osp.abspath(sys_cfg.sims_path),job_id) url_prefix = pxp.join(sys_cfg.url_root,sys_cfg.sims_url_path,job_id) logging.debug('make_kmz: job_path %s' % job_path) logging.debug('make_kmz: url_prefix %s' % url_prefix) if mode == '' or mode == "inc": kmz_filename = job_id + '_inc.kmz' href_prefix = osp.abspath(job_path) href_join = osp.join logging.debug('make_kmz: kmz file will include images from %s' % href_prefix) logging.info('make_kmz: kmz file will include images') elif mode == "ref": kmz_filename = job_id + '_ref.kmz' href_prefix = url_prefix href_join = pxp.join logging.debug('make_kmz: kmz file will link to images from %s' % href_prefix) logging.info('make_kmz: kmz file will link to images') else: logging.error('make_kmz: arg 2 must be "inc" or "ref" or omitted') exit(1) # read the catalog and the manifest cat_path = osp.join(job_path,'catalog.json') cat = json.load(open(cat_path)) if job_id not in cat: logging.error('job id %s not in the catalog' % job_id) sys.exit(1) cat_entry = cat[job_id] mf = json.load(open(osp.join(sys_cfg.sims_path,cat_entry['manifest_path']))) mdomain = max(map(int, mf.keys())) if steps=='': step=[1] else: step=map(int, steps.split(',')) if len(step) == 1: step = step*mdomain elif len(step) != mdomain: logging.error('make_kmz: steps needed for all up to max domain number = %s' % mdomain) sys.exit(1) description = cat_entry['description'] logging.info('make_kmz: job description: %s' % description) # transpose var and time in manifest, output to frame frame={} for domain in mf: for ts_esmf in mf[domain]: for var in mf[domain][ts_esmf]: if only_vars is None or var in only_vars: update_nested_dict(frame,{domain:{var:{ts_esmf:mf[domain][ts_esmf][var]}}}) doc = kml.Kml(name=description) for domain in sorted(frame): domain_folder = doc.newfolder(name = domain) istep = step[int(domain)-1] logging.info('make_kmz: processing domain %s step %s' % (domain, istep)) for var in frame[domain]: var_folder = domain_folder.newfolder(name = var) ts_esmf = sorted(frame[domain][var].keys()) ts_esmf = ts_esmf[1::istep] ts_esmf1 = ts_esmf[1:] ts_esmf1.append(None) for ts_esmf,ts_esmf1 in zip(ts_esmf,ts_esmf1): ts_folder = var_folder.newfolder(name = ts_esmf) ts_folder.timespan.begin = ts_esmf.replace('_','T')+'Z' if ts_esmf1 is not None: ts_folder.timespan.end = ts_esmf1.replace('_','T')+'Z' frame_data = frame[domain][var][ts_esmf] raster_path = frame_data['raster'] coords = frame_data['coords'] if 'colorbar' in frame_data: # add colorbar to KMZ cb_path = frame_data['colorbar'] cbo = ts_folder.newscreenoverlay(name='colorbar') cbo.overlayxy = kml.OverlayXY(x=0,y=1,xunits=kml.Units.fraction,yunits=kml.Units.fraction) cbo.screenxy = kml.ScreenXY(x=0.02,y=0.95,xunits=kml.Units.fraction,yunits=kml.Units.fraction) cbo.size = kml.Size(x=150,y=300,xunits=kml.Units.pixel,yunits=kml.Units.pixel) cbo.color = kml.Color.rgb(255,255,255,a=150) cbo.visibility = 0 cbo.icon.href = href_join(href_prefix,cb_path) # add ground overlay ground = ts_folder.newgroundoverlay(name=var,color='80ffffff') ground.gxlatlonquad.coords = coords ground.visibility = 0 ground.icon.href = href_join(href_prefix,raster_path) # build output file kmz_path = osp.join(job_path,kmz_filename) logging.info('make_kmz: creating file %s' % kmz_path) doc.savekmz(kmz_path) url = pxp.join(url_prefix,kmz_filename) logging.info('make_kmz: file created at %s' % url) try: r = requests.get(url, stream=True) content_size = int(r.headers['Content-Length']) logging.info('make_kmz: file size is %s' % content_size) cat[job_id]['kml_url']=url cat[job_id]['kml_size']=content_size json.dump(cat, open(cat_path,'w'), indent=4, separators=(',', ': ')) except: logging.warning('make_kmz: accessing the file over the web failed')
cb_name = 'colorbar-' + base_name + '.png' with open(cb_name, 'w') as f: f.write(cb_png_data) doc.addfile(cb_name) cbo = doc.newscreenoverlay(name='colorbar') cbo.overlayxy = kml.OverlayXY(x=0, y=1, xunits=kml.Units.fraction, yunits=kml.Units.fraction) cbo.screenxy = kml.ScreenXY(x=0.02, y=0.95, xunits=kml.Units.fraction, yunits=kml.Units.fraction) cbo.size = kml.Size(x=150, y=300, xunits=kml.Units.pixel, yunits=kml.Units.pixel) cbo.color = kml.Color.rgb(255, 255, 255, a=150) cbo.visibility = 1 cbo.icon.href = cb_name print( '[raster2kml] rendering raster from variable %s (Mercator projection) ...' % varname) ground = doc.newgroundoverlay(name=varname, color='80ffffff') raster_png_data, corner_coords = basemap_raster_mercator( lon, lat, fa, fa_min, fa_max, cmap) raster_name = 'raster-' + base_name + '.png' with open(raster_name, 'w') as f: f.write(raster_png_data) doc.addfile(raster_name)