def load_mrlc(f): # pale green background by default sfcinfo, surfacelayers = load_raster(f) surface = surfacelayers[0] # nearest-neighbor upsampling creates chunky pixels - smooth # the edges with a median filter since we're in index space. # doing this in the index space keeps sharp edges on the # landcover areas, but rounded rather than blocky. # compare image resolution to 30m. # mrlc is actually 1 arcsecond but 30m is close enough # for choosing a filter parameter. scale = 30.0 / sfcinfo.grid.meters_per_grid() do_median = 1 if do_median and scale > 2.0: # kernel size, an odd number that is near the diameter of an mrlc cell in the image grid ksize = 2 * int(scale / 2) + 1 if ksize > 21: # arbitrary limit so we can scale up without blowing up ksize = 21 surface = ndimage.median_filter(surface, size=(ksize,ksize)) # build the colormap cmap = N.zeros((256,3), N.float32) for code,info in landcover_info.iteritems(): cmap[int(code),:] = [int(cc,16) for cc in re.match('#(..)(..)(..)', info['natural']).groups()] # apply the colormap and transform to 0..1 surface = cmap[surface] / 255.0 return sfcinfo, surface
def load_quarters(fns): """join four quadrants downsampled from the previous (larger) zoom level. this has better locality and requires less warping than extracting from the source data repeatedly at different zooms. the quadrants have overlap for processing reasons, these need to be removed in the middle + the only problem is that the margin for each zoom level decreases by a factor of two, but we don't want to start with a huge margin at the largest zoom. so at some point we have to go into neighboring quarters. """ (swinfo, sw), (seinfo, se), (nwinfo, nw), (neinfo, ne) = (load_raster(fn) for fn in fns) # assume all quarters have the same projection, and compatible geoxf # assume that they are symmetrically arranged, so we can just use sw and ne _, _, ebound, nbound = swinfo.grid.extent() wbound, sbound, _, _ = neinfo.grid.extent() cx = (ebound + wbound) / 2 cy = (nbound + sbound) / 2 # geoxf and srs are the same as swinfo, # but the shape doubles # note assumes meters but extent() returns lat/lon sy, sx = swinfo.grid.shape print "swshape %s" % swinfo.grid.shape ixmin, iymin = N.dot(neinfo.grid.inv_s, (cx, cy)) ixmax, iymax = N.dot(swinfo.grid.inv_s, (cx, cy)) print "overlapped %s pixels in x" % (ixmin + sx - ixmax) print "overlapped %s pixels in y" % (iymin + sy - iymax) big = N.vstack( N.hstack(sw[:iymax, :ixmax, :], se[:iymax, ixmin:, :]), N.hstack(nw[iymin:, :ixmax, :], ne[iymin:, ixmin:, :]) ) print "bigshape %s" % big.shape return biginfo, big
def doit(workdir, grid): extract_all(workdir, grid) # create surface lcf = '%s/mrlc' % (workdir,) if os.path.exists(lcf + '.tif'): sfcinfo, surface = load_mrlc(lcf + '.tif') else: sfcinfo, surface = load_quarters(lcf) #print 'SFCI', sfcinfo # get the hydrography #water = map_nhd(sfcinfo.grid) #print 'WWWWS', water.shape #glumpy_loop(water) demf = '%s/dem' % (workdir,) demtif = demf + '.tif' if os.path.exists(demtif): deminfo, demlayers = load_raster(demtif) else: deminfo, demlayers = load_quarters(lcf) dem = demlayers[0] # XXX handle missing values #glumpy_loop(surface) shaded = reliefshade(deminfo, dem, surface) #glumpy_loop(shaded) # test of grid tiling #for (z,ix,iy) in sfcinfo.grid.itertiles(): # print 'TILE %d %d %d' % (z, ix, iy) #print 'TIFF_HISTO', N.histogram(img, new=True) # if we don't have the DEM in a file (because we just composited it from quadrants), # save it to a file so it can be fed to gdal_contour if not os.path.exists(demtif): save_raster(deminfo, demtif, dem) if not os.path.isdir('%s/contour' % workdir): contour_find(demtif, '%s/contour' % workdir) if not os.path.isdir('%s/contourft' % (workdir,)): ContourTweaker().filter('%s/contour' % (workdir,), '%s/contourft' % (workdir,)) feats = render_layer(workdir, 'features', grid, ['nhd_flowline', 'nhd_waterbody', 'nhd_area', 'osm_line', 'contours']) fills = render_layer(workdir, 'fills', grid, ['contours', 'nhd_flowline', 'nhd_waterbody', 'nhd_area', 'osm_line']) labels = render_layer(workdir, 'labels', grid, ['contours', 'nhd_flowline', 'nhd_waterbody', 'nhd_area', 'osm_line']) # add contour labels and features img = asum(shaded, halo_mask(feats, labels)) img = asum(img, fills) img = asum(img, labels) # build half-resolution versions for next zoom level #if not os.path.isdir('%s/quarter' % (workdir,)): # os.mkdir('%s/quarter' % (workdir,)) # XXX doesn't do anything right now parentgrid = sfcinfo.grid # XXX need to figure these out based on ix%2, iy%2 at some zoom? is_east = 0 is_north = 0 quadrant = [['sw', 'se'], ['nw', 'ne']][is_north][is_east] mrlcdir = request_workdir(parentgrid, 'mrlc') build_quarter('%s/%s.tif' % (mrlcdir,quadrant), sfcinfo, surface) demdir = request_workdir(parentgrid, 'dem') build_quarter('%s/%s.tif' % (demdir,quadrant), deminfo, dem) return img