Пример #1
0
def test_is_same_crs():
    crs1 = {'init': 'EPSG:4326'}
    crs2 = {'init': 'EPSG:3857'}

    assert is_same_crs(crs1, crs1) is True
    assert is_same_crs(crs1, crs2) is False

    wgs84_crs = crs.from_string('+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs')
    assert is_same_crs(crs1, wgs84_crs) is True

    # Make sure that same projection with different parameter are not equal
    lcc_crs1 = crs.from_string('+lon_0=-95 +ellps=GRS80 +y_0=0 +no_defs=True +proj=lcc +x_0=0 +units=m +lat_2=77 +lat_1=49 +lat_0=0')
    lcc_crs2 = crs.from_string('+lon_0=-95 +ellps=GRS80 +y_0=0 +no_defs=True +proj=lcc +x_0=0 +units=m +lat_2=77 +lat_1=45 +lat_0=0')
    assert is_same_crs(lcc_crs1, lcc_crs2) is False
Пример #2
0
def test_is_same_crs():
    crs1 = {'init': 'EPSG:4326'}
    crs2 = {'init': 'EPSG:3857'}

    assert is_same_crs(crs1, crs1) is True
    assert is_same_crs(crs1, crs2) is False

    wgs84_crs = crs.from_string(
        '+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs')
    assert is_same_crs(crs1, wgs84_crs) is True

    # Make sure that same projection with different parameter are not equal
    lcc_crs1 = crs.from_string(
        '+lon_0=-95 +ellps=GRS80 +y_0=0 +no_defs=True +proj=lcc +x_0=0 +units=m +lat_2=77 +lat_1=49 +lat_0=0'
    )
    lcc_crs2 = crs.from_string(
        '+lon_0=-95 +ellps=GRS80 +y_0=0 +no_defs=True +proj=lcc +x_0=0 +units=m +lat_2=77 +lat_1=45 +lat_0=0'
    )
    assert is_same_crs(lcc_crs1, lcc_crs2) is False
Пример #3
0
def rasterize(ctx, files, driver, like, bounds, dimensions, res, src_crs,
              all_touched, default_value, fill, property):
    """Rasterize GeoJSON into a new or existing raster.

    If the output raster exists, rio-rasterize will rasterize feature values
    into all bands of that raster.  The GeoJSON is assumed to be in the same
    coordinate reference system as the output unless --src-crs is provided.

    --default_value or property values when using --property must be using a
    data type valid for the data type of that raster.


    If a template raster is provided using the --like option, the affine
    transform and data type from that raster will be used to create the output.
    Only a single band will be output.

    The GeoJSON is assumed to be in the same coordinate reference system unless
    --src-crs is provided.

    --default_value or property values when using --property must be using a
    data type valid for the data type of that raster.

    --driver, --bounds, --dimensions, and --res are ignored when output exists
    or --like raster is provided


    If the output does not exist and --like raster is not provided, the input
    GeoJSON will be used to determine the bounds of the output unless
    provided using --bounds.

    --dimensions or --res are required in this case.

    If --res is provided, the bottom and right coordinates of bounds are
    ignored.


    Note:
    The GeoJSON is not projected to match the coordinate reference system
    of the output or --like rasters at this time.  This functionality may be
    added in the future.
    """

    from rasterio._base import is_geographic_crs, is_same_crs
    from rasterio.features import rasterize
    from rasterio.features import bounds as calculate_bounds

    verbosity = (ctx.obj and ctx.obj.get('verbosity')) or 1

    files = list(files)
    output = files.pop()
    input = click.open_file(files.pop(0) if files else '-')
    has_src_crs = src_crs is not None
    src_crs = src_crs or 'EPSG:4326'

    # If values are actually meant to be integers, we need to cast them
    # as such or rasterize creates floating point outputs
    if default_value == int(default_value):
        default_value = int(default_value)
    if fill == int(fill):
        fill = int(fill)

    with rasterio.drivers(CPL_DEBUG=verbosity > 2):

        def feature_value(feature):
            if property and 'properties' in feature:
                return feature['properties'].get(property, default_value)
            return default_value

        geojson = json.loads(input.read())
        if 'features' in geojson:
            geometries = []
            for f in geojson['features']:
                geometries.append((f['geometry'], feature_value(f)))
        elif 'geometry' in geojson:
            geometries = ((geojson['geometry'], feature_value(geojson)), )
        else:
            raise click.BadParameter('Invalid GeoJSON',
                                     param=input,
                                     param_hint='input')

        geojson_bounds = geojson.get('bbox', calculate_bounds(geojson))

        if os.path.exists(output):
            with rasterio.open(output, 'r+') as out:
                if has_src_crs and not is_same_crs(src_crs, out.crs):
                    raise click.BadParameter(
                        'GeoJSON does not match crs of '
                        'existing output raster',
                        param='input',
                        param_hint='input')

                if _disjoint_bounds(geojson_bounds, out.bounds):
                    click.echo(
                        "GeoJSON outside bounds of existing output "
                        "raster. Are they in different coordinate "
                        "reference systems?",
                        err=True)

                meta = out.meta.copy()

                result = rasterize(geometries,
                                   out_shape=(meta['height'], meta['width']),
                                   transform=meta.get('affine',
                                                      meta['transform']),
                                   all_touched=all_touched,
                                   dtype=meta.get('dtype', None),
                                   default_value=default_value,
                                   fill=fill)

                for bidx in range(1, meta['count'] + 1):
                    data = out.read_band(bidx, masked=True)
                    # Burn in any non-fill pixels, and update mask accordingly
                    ne = result != fill
                    data[ne] = result[ne]
                    data.mask[ne] = False
                    out.write_band(bidx, data)

        else:
            if like is not None:
                template_ds = rasterio.open(like)

                if has_src_crs and not is_same_crs(src_crs, template_ds.crs):
                    raise click.BadParameter(
                        'GeoJSON does not match crs of '
                        '--like raster',
                        param='input',
                        param_hint='input')

                if _disjoint_bounds(geojson_bounds, template_ds.bounds):
                    click.echo(
                        "GeoJSON outside bounds of --like raster. "
                        "Are they in different coordinate reference "
                        "systems?",
                        err=True)

                kwargs = template_ds.meta.copy()
                kwargs['count'] = 1
                template_ds.close()

            else:
                bounds = bounds or geojson_bounds

                if is_geographic_crs(src_crs):
                    if (bounds[0] < -180 or bounds[2] > 180 or bounds[1] < -80
                            or bounds[3] > 80):
                        raise click.BadParameter(
                            "Bounds are beyond the valid extent for "
                            "EPSG:4326.",
                            ctx,
                            param=bounds,
                            param_hint='--bounds')

                if dimensions:
                    width, height = dimensions
                    res = ((bounds[2] - bounds[0]) / float(width),
                           (bounds[3] - bounds[1]) / float(height))

                else:
                    if not res:
                        raise click.BadParameter(
                            'pixel dimensions are required',
                            ctx,
                            param=res,
                            param_hint='--res')
                    elif len(res) == 1:
                        res = (res[0], res[0])

                    width = max(
                        int(ceil((bounds[2] - bounds[0]) / float(res[0]))), 1)
                    height = max(
                        int(ceil((bounds[3] - bounds[1]) / float(res[1]))), 1)

                src_crs = src_crs.upper()
                if not src_crs.count('EPSG:'):
                    raise click.BadParameter(
                        'invalid CRS.  Must be an EPSG code.',
                        ctx,
                        param=src_crs,
                        param_hint='--src_crs')

                kwargs = {
                    'count':
                    1,
                    'crs':
                    src_crs,
                    'width':
                    width,
                    'height':
                    height,
                    'transform':
                    Affine(res[0], 0, bounds[0], 0, -res[1], bounds[3]),
                    'driver':
                    driver
                }

            result = rasterize(geometries,
                               out_shape=(kwargs['height'], kwargs['width']),
                               transform=kwargs.get('affine',
                                                    kwargs['transform']),
                               all_touched=all_touched,
                               dtype=kwargs.get('dtype', None),
                               default_value=default_value,
                               fill=fill)

            if 'dtype' not in kwargs:
                kwargs['dtype'] = result.dtype

            kwargs['nodata'] = fill

            with rasterio.open(output, 'w', **kwargs) as out:
                out.write_band(1, result)
Пример #4
0
def rasterize(
        ctx,
        files,
        output,
        driver,
        like,
        bounds,
        dimensions,
        res,
        src_crs,
        all_touched,
        default_value,
        fill,
        property,
        creation_options):

    """Rasterize GeoJSON into a new or existing raster.

    If the output raster exists, rio-rasterize will rasterize feature values
    into all bands of that raster.  The GeoJSON is assumed to be in the same
    coordinate reference system as the output unless --src-crs is provided.

    --default_value or property values when using --property must be using a
    data type valid for the data type of that raster.


    If a template raster is provided using the --like option, the affine
    transform and data type from that raster will be used to create the output.
    Only a single band will be output.

    The GeoJSON is assumed to be in the same coordinate reference system unless
    --src-crs is provided.

    --default_value or property values when using --property must be using a
    data type valid for the data type of that raster.

    --driver, --bounds, --dimensions, and --res are ignored when output exists
    or --like raster is provided


    If the output does not exist and --like raster is not provided, the input
    GeoJSON will be used to determine the bounds of the output unless
    provided using --bounds.

    --dimensions or --res are required in this case.

    If --res is provided, the bottom and right coordinates of bounds are
    ignored.


    Note:
    The GeoJSON is not projected to match the coordinate reference system
    of the output or --like rasters at this time.  This functionality may be
    added in the future.
    """

    from rasterio._base import is_geographic_crs, is_same_crs
    from rasterio.features import rasterize
    from rasterio.features import bounds as calculate_bounds

    verbosity = (ctx.obj and ctx.obj.get('verbosity')) or 1

    output, files = resolve_inout(files=files, output=output)

    has_src_crs = src_crs is not None
    src_crs = src_crs or 'EPSG:4326'

    # If values are actually meant to be integers, we need to cast them
    # as such or rasterize creates floating point outputs
    if default_value == int(default_value):
        default_value = int(default_value)
    if fill == int(fill):
        fill = int(fill)

    with rasterio.drivers(CPL_DEBUG=verbosity > 2):

        def feature_value(feature):
            if property and 'properties' in feature:
                return feature['properties'].get(property, default_value)
            return default_value

        with click.open_file(files.pop(0) if files else '-') as gj_f:
            geojson = json.loads(gj_f.read())
        if 'features' in geojson:
            geometries = []
            for f in geojson['features']:
                geometries.append((f['geometry'], feature_value(f)))
        elif 'geometry' in geojson:
            geometries = ((geojson['geometry'], feature_value(geojson)), )
        else:
            raise click.BadParameter('Invalid GeoJSON', param=input,
                                     param_hint='input')

        geojson_bounds = geojson.get('bbox', calculate_bounds(geojson))

        if os.path.exists(output):
            with rasterio.open(output, 'r+') as out:
                if has_src_crs and not is_same_crs(src_crs, out.crs):
                    raise click.BadParameter('GeoJSON does not match crs of '
                                             'existing output raster',
                                             param='input', param_hint='input')

                if disjoint_bounds(geojson_bounds, out.bounds):
                    click.echo("GeoJSON outside bounds of existing output "
                               "raster. Are they in different coordinate "
                               "reference systems?",
                               err=True)

                meta = out.meta.copy()

                result = rasterize(
                    geometries,
                    out_shape=(meta['height'], meta['width']),
                    transform=meta.get('affine', meta['transform']),
                    all_touched=all_touched,
                    dtype=meta.get('dtype', None),
                    default_value=default_value,
                    fill = fill)

                for bidx in range(1, meta['count'] + 1):
                    data = out.read(bidx, masked=True)
                    # Burn in any non-fill pixels, and update mask accordingly
                    ne = result != fill
                    data[ne] = result[ne]
                    data.mask[ne] = False
                    out.write_band(bidx, data)

        else:
            if like is not None:
                template_ds = rasterio.open(like)

                if has_src_crs and not is_same_crs(src_crs, template_ds.crs):
                    raise click.BadParameter('GeoJSON does not match crs of '
                                             '--like raster',
                                             param='input', param_hint='input')

                if disjoint_bounds(geojson_bounds, template_ds.bounds):
                    click.echo("GeoJSON outside bounds of --like raster. "
                               "Are they in different coordinate reference "
                               "systems?",
                               err=True)

                kwargs = template_ds.meta.copy()
                kwargs['count'] = 1

                # DEPRECATED
                # upgrade transform to affine object or we may get an invalid
                # transform set on output
                kwargs['transform'] = template_ds.affine

                template_ds.close()

            else:
                bounds = bounds or geojson_bounds

                if is_geographic_crs(src_crs):
                    if (bounds[0] < -180 or bounds[2] > 180 or
                            bounds[1] < -80 or bounds[3] > 80):
                        raise click.BadParameter(
                            "Bounds are beyond the valid extent for "
                            "EPSG:4326.",
                            ctx, param=bounds, param_hint='--bounds')

                if dimensions:
                    width, height = dimensions
                    res = (
                        (bounds[2] - bounds[0]) / float(width),
                        (bounds[3] - bounds[1]) / float(height)
                    )

                else:
                    if not res:
                        raise click.BadParameter(
                            'pixel dimensions are required',
                            ctx, param=res, param_hint='--res')

                    elif len(res) == 1:
                        res = (res[0], res[0])

                    width = max(int(ceil((bounds[2] - bounds[0]) /
                                float(res[0]))), 1)
                    height = max(int(ceil((bounds[3] - bounds[1]) /
                                 float(res[1]))), 1)

                src_crs = src_crs.upper()
                if not src_crs.count('EPSG:'):
                    raise click.BadParameter(
                        'invalid CRS.  Must be an EPSG code.',
                        ctx, param=src_crs, param_hint='--src_crs')

                kwargs = {
                    'count': 1,
                    'crs': src_crs,
                    'width': width,
                    'height': height,
                    'transform': Affine(res[0], 0, bounds[0], 0, -res[1],
                                        bounds[3]),
                    'driver': driver
                }
                kwargs.update(**creation_options)

            result = rasterize(
                geometries,
                out_shape=(kwargs['height'], kwargs['width']),
                transform=kwargs.get('affine', kwargs['transform']),
                all_touched=all_touched,
                dtype=kwargs.get('dtype', None),
                default_value=default_value,
                fill = fill)

            if 'dtype' not in kwargs:
                kwargs['dtype'] = result.dtype

            kwargs['nodata'] = fill

            with rasterio.open(output, 'w', **kwargs) as out:
                out.write_band(1, result)
Пример #5
0
def rasterize(
        geojson,
        output,
        like=None,
        bounds=None,
        dimensions=None,
        res=None,
        src_crs=None,
        all_touched=None,
        default_value=1,
        fill=0,
        prop=None,
        force_overwrite=None,
        creation_options={},
        driver='GTiff'):

    from rasterio._base import is_geographic_crs, is_same_crs
    from rasterio.features import rasterize
    from rasterio.features import bounds as calculate_bounds

    has_src_crs = src_crs is not None
    src_crs = src_crs or 'EPSG:4326'

    # If values are actually meant to be integers, we need to cast them
    # as such or rasterize creates floating point outputs
    if default_value == int(default_value):
        default_value = int(default_value)
    if fill == int(fill):
        fill = int(fill)

    with rasterio.drivers():

        def feature_value(feature):
            if prop and 'properties' in feature:
                return feature['properties'].get(prop, default_value)
            return default_value

        if 'features' in geojson:
            geometries = []
            for f in geojson['features']:
                geometries.append((f['geometry'], feature_value(f)))
        elif 'geometry' in geojson:
            geometries = ((geojson['geometry'], feature_value(geojson)), )
        else:
            raise Exception

        geojson_bounds = geojson.get('bbox', calculate_bounds(geojson))

        if like is not None:
            template_ds = rasterio.open(like)

            if has_src_crs and not is_same_crs(src_crs, template_ds.crs):
                raise Exception

            if disjoint_bounds(geojson_bounds, template_ds.bounds):
                print "GeoJSON outside bounds of --like raster. "

            kwargs = template_ds.meta.copy()
            kwargs['count'] = 1

            # DEPRECATED
            # upgrade transform to affine object or we may get an invalid
            # transform set on output
            kwargs['transform'] = template_ds.affine

            template_ds.close()

        else:
            bounds = bounds or geojson_bounds

            if is_geographic_crs(src_crs):
                if (bounds[0] < -180 or bounds[2] > 180 or
                        bounds[1] < -80 or bounds[3] > 80):
                    raise Exception

            if dimensions:
                width, height = dimensions
                res = (
                    (bounds[2] - bounds[0]) / float(width),
                    (bounds[3] - bounds[1]) / float(height)
                )

            else:
                if not res:
                    raise Exception

                elif len(res) == 1:
                    res = (res[0], res[0])

                width = max(int(ceil((bounds[2] - bounds[0]) /
                            float(res[0]))), 1)
                height = max(int(ceil((bounds[3] - bounds[1]) /
                             float(res[1]))), 1)

            src_crs = src_crs.upper()
            if not src_crs.count('EPSG:'):
                raise Exception

            kwargs = {
                'count': 1,
                'crs': src_crs,
                'width': width,
                'height': height,
                'transform': Affine(res[0], 0, bounds[0], 0, -res[1],
                                    bounds[3]),
                'driver': driver
            }
            kwargs.update(**creation_options)

        result = rasterize(
            geometries,
            out_shape=(kwargs['height'], kwargs['width']),
            transform=kwargs.get('affine', kwargs['transform']),
            all_touched=all_touched,
            dtype=kwargs.get('dtype', None),
            default_value=default_value,
            fill = fill)

        if 'dtype' not in kwargs:
            kwargs['dtype'] = result.dtype

        kwargs['nodata'] = fill

        with rasterio.open(output, 'w', **kwargs) as out:
            out.write_band(1, result)