def test_projection(): bbox = BBox(TEST_COORDS, TEST_COORDS_PRJ) proj_bbox = bbox.project(Proj(init="EPSG:3857")) # Calculated by running this previously under controlled conditions. No validation against truth of projection values. assert numpy.allclose(proj_bbox.as_list(), [ -13887106.476460878, 6211469.632719522, -13845361.6674134, 6274861.394006577 ])
def render_tif(filename_pattern, output_directory, renderer_file, save, renderer_type, colormap, colorspace, palette, scale, id_variable, lh, legend_breaks, legend_ticks, src_crs, dst_crs, res, resampling, anchors): """ Render single-band GeoTIFF files to images. colormap is ignored if renderer_file is provided """ filenames = glob.glob(filename_pattern) if not filenames: raise click.BadParameter('No files found matching that pattern', param='filename_pattern', param_hint='FILENAME_PATTERN') if not os.path.exists(output_directory): os.makedirs(output_directory) if renderer_file is not None and not save: if not os.path.exists(renderer_file): raise click.BadParameter('does not exist', param='renderer_file', param_hint='renderer_file') # see https://bitbucket.org/databasin/ncdjango/wiki/Home for format renderer_dict = json.loads(open(renderer_file).read()) # if renderer_dict['type'] == 'stretched': # colors = ','.join([str(c[0]) for c in renderer_dict['colors']]) # if 'min' in colors or 'max' in colors or 'mean' in colors: # statistics = collect_statistics(filenames, (variable,))[variable] # for entry in renderer_dict['colors']: # if isinstance(entry[0], basestring): # if entry[0] in ('min', 'max', 'mean'): # entry[0] = statistics[entry[0]] # elif '*' in entry[0]: # rel_value, statistic = entry[0].split('*') # entry[0] = float(rel_value) * statistics[statistic] renderer = renderer_from_dict(renderer_dict) else: if renderer_type == 'stretched': # if palette is not None: # renderer = _palette_to_stretched_renderer(palette, 'min,max', filenames, variable) # # else: renderer = _colormap_to_stretched_renderer(colormap, colorspace, filenames) elif renderer_type == 'unique': renderer = UniqueValuesRenderer(_parse_colormap(colormap), colorspace) else: raise NotImplementedError('other renderers not yet built') # if save: # if not renderer_file: # raise click.BadParameter('must be provided to save', param='renderer_file', param_hint='renderer_file') # # if os.path.exists(renderer_file): # with open(renderer_file, 'r+') as output_file: # data = json.loads(output_file.read()) # output_file.seek(0) # output_file.truncate() # data[variable] = renderer.serialize() # output_file.write(json.dumps(data, indent=4)) # else: # with open(renderer_file, 'w') as output_file: # output_file.write(json.dumps({variable: renderer.serialize()})) if renderer_type == 'streteched': if legend_ticks is not None and not legend_breaks: legend_ticks = [float(v) for v in legend_ticks.split(',')] legend = renderer.get_legend(image_height=lh, breaks=legend_breaks, ticks=legend_ticks, max_precision=2)[0].to_image() elif renderer_type == 'unique': legend = renderer.get_legend(image_height=lh)[0].to_image() legend.save(os.path.join(output_directory, 'legend.png')) for filename in filenames: with rasterio.open(filename) as ds: print('Processing', filename) filename_root = os.path.split(filename)[1].replace('.nc', '') data = ds.read(1, masked=True) # # get transforms, assume last 2 dimensions on variable are spatial in row, col order # y_dim, x_dim = ds.variables[variable].dimensions[-2:] # y_len, x_len = data.shape[-2:] # coords = SpatialCoordinateVariables.from_dataset(ds, x_dim, y_dim)#, projection=Proj(src_crs)) # # if coords.y.is_ascending_order(): # data = data[::-1] # reproject_kwargs = None if dst_crs is not None: # TODO: extract this out into a general clover reprojection function ds_crs = ds.crs if not (src_crs or ds_crs): raise click.BadParameter( 'must provide src_crs to reproject', param='src_crs', param_hint='src_crs') dst_crs = {'init': dst_crs} src_crs = ds_crs if ds_crs else {'init': src_crs} left, bottom, top, right = ds.bounds dst_affine, dst_width, dst_height = calculate_default_transform( left, bottom, right, top, ds.width, ds.height, src_crs, dst_crs) dst_shape = (dst_height, dst_width) # proj_bbox = coords.bbox.project(Proj(dst_crs)) # # x_dif = proj_bbox.xmax - proj_bbox.xmin # y_dif = proj_bbox.ymax - proj_bbox.ymin # # total_len = float(x_len + y_len) # # Cellsize is dimension weighted average of x and y dimensions per projected pixel, unless otherwise provided # avg_cellsize = ((x_dif / float(x_len)) * (float(x_len) / total_len)) + ((y_dif / float(y_len)) * (float(y_len) / total_len)) # # cellsize = res or avg_cellsize # dst_affine = Affine(cellsize, 0, proj_bbox.xmin, 0, -cellsize, proj_bbox.ymax) # dst_shape = ( # max(int(ceil((y_dif) / cellsize)), 1), # height # max(int(ceil(x_dif / cellsize)), 1) # width # ) # TODO: replace with method in rasterio reproject_kwargs = { 'src_crs': src_crs, 'src_transform': ds.affine, 'dst_crs': dst_crs, 'dst_transform': dst_affine, 'resampling': getattr(RESAMPLING, resampling), 'dst_shape': dst_shape } if anchors: # Reproject the bbox of the output to WGS84 full_bbox = BBox( (dst_affine.c, dst_affine.f + dst_affine.e * dst_shape[0], dst_affine.c + dst_affine.a * dst_shape[1], dst_affine.f), projection=Proj(dst_crs)) wgs84_bbox = full_bbox.project(Proj(init='EPSG:4326')) print('WGS84 Anchors: {0}'.format( [[wgs84_bbox.ymin, wgs84_bbox.xmin], [wgs84_bbox.ymax, wgs84_bbox.xmax]])) elif anchors: # Reproject the bbox of the output to WGS84 full_bbox = BBox(ds.bounds, projection=Proj(ds.crs)) wgs84_bbox = full_bbox.project(Proj(init='EPSG:4326')) print('WGS84 Anchors: {0}'.format( [[wgs84_bbox.ymin, wgs84_bbox.xmin], [wgs84_bbox.ymax, wgs84_bbox.xmax]])) image_filename = os.path.join(output_directory, '{0}.png'.format(filename_root)) render_image(renderer, data, image_filename, scale, reproject_kwargs=reproject_kwargs)