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 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 get_results_image(self, bounds, size, single_color, kept_colors, gained_colors, species, historic, futures): kept_colors = self.get_colors(kept_colors, len(futures)+1) gained_colors = self.get_colors(gained_colors, len(futures)+1) extent = BBox(bounds, projection=WGS84) self.service = Service.objects.get(name='{}_p{}_800m_pa'.format(species, historic)) variable = self.service.variable_set.all().first() native_extent = extent.project(Proj(str(variable.projection))) coords = SpatialCoordinateVariables.from_bbox(variable.full_extent, *self.get_grid_spatial_dimensions(variable)) x_slice = coords.x.indices_for_range(native_extent.xmin, native_extent.xmax) y_slice = coords.y.indices_for_range(native_extent.ymin, native_extent.ymax) historic_data = self.get_grid_for_variable(variable, x_slice=x_slice, y_slice=y_slice) self.close_dataset() if not futures: data = historic_data renderer = UniqueValuesRenderer([(1, Color.from_hex(single_color))], fill_value=0) else: future_grids = [] for future in futures: self.service = Service.objects.get(name='{}_15gcm_{}_pa'.format(species, future)) variable = self.service.variable_set.all().first() future_grids.append(self.get_grid_for_variable(variable, x_slice=x_slice, y_slice=y_slice)) self.close_dataset() future_data = sum(future_grids) del future_grids data = numpy.zeros_like(historic_data, numpy.uint8) data[historic_data == 1] = 1 kept_idx = (historic_data == 1) & (future_data > 0) data[kept_idx] = future_data[kept_idx] + 1 gained_idx = (historic_data == 0) & (future_data > 0) data[gained_idx] = future_data[gained_idx] + len(kept_colors) + 1 data[data.mask == 1] = 0 values = numpy.unique(data) renderer = UniqueValuesRenderer( [ (i+1, Color.from_hex(c)) for (i, c) in enumerate(kept_colors) if i+1 in values ] + [ (i+len(kept_colors)+1, Color.from_hex(c)) for (i, c) in enumerate(gained_colors) if i+len(kept_colors)+1 in values ], fill_value=0 ) image = renderer.render_image(data.data).convert('RGBA') return GeoImage(image, native_extent).warp(extent, size).image
def get(self, request, *args, **kwargs): tile_bounds = list( mercantile.bounds(int(self.kwargs['x']), int(self.kwargs['y']), int(self.kwargs['z']))) extent = BBox(tile_bounds, projection=WGS84).project(WEB_MERCATOR) try: service_names = request.GET['services'].split(',') except KeyError: return HttpResponse(status=400) grids = [] for service_name in service_names: self.service = Service.objects.get(name=service_name) variable = self.service.variable_set.all()[:1].get() native_extent = extent.project( pyproj.Proj(str(variable.projection))) dimensions = self.get_grid_spatial_dimensions(variable) cell_size = (float(variable.full_extent.width) / dimensions[0], float(variable.full_extent.height) / dimensions[1]) grid_bounds = [ int( math.floor( float(native_extent.xmin - variable.full_extent.xmin) / cell_size[0])) - 1, int( math.floor( float(native_extent.ymin - variable.full_extent.ymin) / cell_size[1])) - 1, int( math.ceil( float(native_extent.xmax - variable.full_extent.xmin) / cell_size[0])) + 1, int( math.ceil( float(native_extent.ymax - variable.full_extent.ymin) / cell_size[1])) + 1 ] grid_bounds = [ min(max(grid_bounds[0], 0), dimensions[0]), min(max(grid_bounds[1], 0), dimensions[1]), min(max(grid_bounds[2], 0), dimensions[0]), min(max(grid_bounds[3], 0), dimensions[1]) ] if not (grid_bounds[2] - grid_bounds[0] and grid_bounds[3] - grid_bounds[1]): continue grid_extent = BBox( (variable.full_extent.xmin + grid_bounds[0] * cell_size[0], variable.full_extent.ymin + grid_bounds[1] * cell_size[1], variable.full_extent.xmin + grid_bounds[2] * cell_size[0], variable.full_extent.ymin + grid_bounds[3] * cell_size[1]), native_extent.projection) if not self.is_y_increasing(variable): y_max = dimensions[1] - grid_bounds[1] y_min = dimensions[1] - grid_bounds[3] grid_bounds[1] = y_min grid_bounds[3] = y_max grids.append( self.get_grid_for_variable(variable, x_slice=(grid_bounds[0], grid_bounds[2]), y_slice=(grid_bounds[1], grid_bounds[3]))) self.close_dataset() intersection = reduce(lambda x, y: x & y, grids) image = RENDERER.render_image( intersection, row_major_order=self.is_row_major(variable)).convert('RGBA') # If y values are increasing, the rendered image needs to be flipped vertically if self.is_y_increasing(variable): image = image.transpose(Image.FLIP_TOP_BOTTOM) image = GeoImage(image, grid_extent).warp(extent, TILE_SIZE).image image, content_type = self.format_image(image, 'png') return self.create_response(request, image, content_type)
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 trefoil 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)
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 trefoil 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)