Exemplo n.º 1
0
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]
    )
Exemplo n.º 2
0
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
    ])
Exemplo n.º 3
0
    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
Exemplo n.º 4
0
    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)
Exemplo n.º 5
0
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)
Exemplo n.º 6
0
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)