def file_in_handler(ctx, param, value): """Normalize ordinary filesystem and VFS paths""" try: path, archive, scheme = parse_path(value) # Validate existence of files. if scheme in FILE_SCHEMES and not \ rasterio.shutil.exists(value): raise IOError( "Input file {0} does not exist".format(value)) if archive and scheme: archive = abspath_forward_slashes(archive) path = "{0}://{1}!{2}".format(scheme, archive, path) elif scheme and scheme.startswith('http'): path = "{0}://{1}".format(scheme, path) elif scheme == 's3': path = "{0}://{1}".format(scheme, path) elif scheme in FILE_SCHEMES: path = abspath_forward_slashes(path) else: path = path return path except Exception: raise click.BadParameter("{} is not a valid input file".format(value))
def file_in_handler(ctx, param, value): """Normalize ordinary filesystem and VFS paths""" try: path, archive, scheme = parse_path(value) path_to_check = archive or path # Validate existence of files. if scheme in FILE_SCHEMES and not os.path.exists(path_to_check): raise IOError( "Input file {0} does not exist".format(path_to_check)) if archive and scheme: archive = abspath_forward_slashes(archive) path = "{0}://{1}!{2}".format(scheme, archive, path) elif scheme and scheme.startswith('http'): path = "{0}://{1}".format(scheme, path) elif scheme == 's3': path = "{0}://{1}".format(scheme, path) elif scheme in FILE_SCHEMES: path = abspath_forward_slashes(path) else: path = path return path except Exception: raise click.BadParameter("{} is not a valid input file".format(value))
def file_in_handler(ctx, param, value): """Normalize ordinary filesystem and VFS paths""" try: path, archive, scheme = parse_path(value) except ValueError as exc: raise click.BadParameter(str(exc)) path_to_check = archive or path if not os.path.exists(path_to_check): raise click.BadParameter("Input file {0} does not exist".format(path_to_check)) if archive and scheme: archive = os.path.abspath(archive) path = "{0}://{1}!{2}".format(scheme, archive, path) else: path = os.path.abspath(path) return path
def file_in_handler(ctx, param, value): """Normalize ordinary filesystem and VFS paths""" try: path, archive, scheme = parse_path(value) except ValueError as exc: raise click.BadParameter(str(exc)) path_to_check = archive or path if not os.path.exists(path_to_check): raise click.BadParameter( "Input file {0} does not exist".format(path_to_check)) if archive and scheme: archive = os.path.abspath(archive) path = "{0}://{1}!{2}".format(scheme, archive, path) else: path = os.path.abspath(path) return path
def file_in_handler(ctx, param, value): """Normalize ordinary filesystem and VFS paths""" try: path, archive, scheme = parse_path(value) except ValueError as exc: raise click.BadParameter(str(exc)) path_to_check = archive or path if not scheme in ['http', 'https', 's3'] and not os.path.exists(path_to_check): raise click.BadParameter( "Input file {0} does not exist".format(path_to_check)) if archive and scheme: archive = abspath_forward_slashes(archive) path = "{0}://{1}!{2}".format(scheme, archive, path) elif scheme and scheme.startswith('http'): path = "{0}://{1}".format(scheme, path) elif scheme == 's3': path = "{0}://{1}".format(scheme, path) else: path = abspath_forward_slashes(path) return path
def file_in_handler(ctx, param, value): """Normalize ordinary filesystem and VFS paths""" try: path, archive, scheme = parse_path(value) path_to_check = archive or path if (scheme not in ['http', 'https', 's3'] and not os.path.exists(path_to_check)): raise IOError( "Input file {0} does not exist".format(path_to_check)) if archive and scheme: archive = abspath_forward_slashes(archive) path = "{0}://{1}!{2}".format(scheme, archive, path) elif scheme and scheme.startswith('http'): path = "{0}://{1}".format(scheme, path) elif scheme == 's3': path = "{0}://{1}".format(scheme, path) else: path = abspath_forward_slashes(path) return path except Exception: raise click.BadParameter("{} is not a valid input file".format(value))
def test_parse_path_file_scheme(): """Correctly parse file:// URL""" assert parse_path('file://foo.tif') == ( 'foo.tif', None, 'file')
def test_parse_path_zip(): """Correctly parse VFS scheme URL""" assert parse_path('zip://tests/data/files.zip!foo.tif') == ( 'foo.tif', 'tests/data/files.zip', 'zip')
def test_parse_path_with_vfs(): """Warn deprecation of old parse_path""" with pytest.warns(RasterioDeprecationWarning): assert parse_path('foo.tif', vfs='zip://tests/data/files.zip') == ('foo.tif', 'tests/data/files.zip', 'zip')
def open(path, mode='r', driver=None, width=None, height=None, count=None, crs=None, transform=None, dtype=None, nodata=None, **kwargs): """Open file at ``path`` in ``mode`` 'r' (read), 'r+' (read and write), or 'w' (write) and return a dataset Reader or Updater object. In write mode, a driver name such as "GTiff" or "JPEG" (see GDAL docs or ``gdal_translate --help`` on the command line), ``width`` (number of pixels per line) and ``height`` (number of lines), the ``count`` number of bands in the new file must be specified. Additionally, the data type for bands such as ``rasterio.ubyte`` for 8-bit bands or ``rasterio.uint16`` for 16-bit bands must be specified using the ``dtype`` argument. Parameters ---------- mode: string "r" (read), "r+" (read/write), or "w" (write) driver: string driver code specifying the format name (e.g. "GTiff" or "JPEG"). See GDAL docs at http://www.gdal.org/formats_list.html (optional, required for writing). width: int number of pixels per line (optional, required for write) height: int number of lines (optional, required for write) count: int > 0 number of bands (optional, required for write) dtype: rasterio.dtype the data type for bands such as ``rasterio.ubyte`` for 8-bit bands or ``rasterio.uint16`` for 16-bit bands (optional, required for write) crs: dict or string Coordinate reference system (optional, recommended for write) transform: Affine instance Affine transformation mapping the pixel space to geographic space (optional, recommended for writing). nodata: number Defines pixel value to be interpreted as null/nodata (optional, recommended for write) Returns ------- A ``DatasetReader`` or ``DatasetUpdater`` object. Notes ----- In write mode, you must specify at least ``width``, ``height``, ``count`` and ``dtype``. A coordinate reference system for raster datasets in write mode can be defined by the ``crs`` argument. It takes Proj4 style mappings like .. code:: {'proj': 'longlat', 'ellps': 'WGS84', 'datum': 'WGS84', 'no_defs': True} An affine transformation that maps ``col,row`` pixel coordinates to ``x,y`` coordinates in the coordinate reference system can be specified using the ``transform`` argument. The value should be an instance of ``affine.Affine`` .. code:: python >>> from affine import Affine >>> Affine(0.5, 0.0, -180.0, 0.0, -0.5, 90.0) These coefficients are shown in the figure below. .. code:: | x | | a b c | | c | | y | = | d e f | | r | | 1 | | 0 0 1 | | 1 | a: rate of change of X with respect to increasing column, i.e. pixel width b: rotation, 0 if the raster is oriented "north up" c: X coordinate of the top left corner of the top left pixel d: rotation, 0 if the raster is oriented "north up" e: rate of change of Y with respect to increasing row, usually a negative number (i.e. -1 * pixel height) if north-up. f: Y coordinate of the top left corner of the top left pixel A 6-element sequence of the affine transformation matrix coefficients in ``c, a, b, f, d, e`` order, (i.e. GDAL geotransform order) will be accepted until 1.0 (deprecated). A virtual filesystem can be specified. The ``vfs`` parameter may be an Apache Commons VFS style string beginning with "zip://" or "tar://"". In this case, the ``path`` must be an absolute path within that container. """ if not isinstance(path, string_types): raise TypeError("invalid path: {0!r}".format(path)) if mode and not isinstance(mode, string_types): raise TypeError("invalid mode: {0!r}".format(mode)) if driver and not isinstance(driver, string_types): raise TypeError("invalid driver: {0!r}".format(driver)) if dtype and not check_dtype(dtype): raise TypeError("invalid dtype: {0!r}".format(dtype)) if transform: transform = guard_transform(transform) elif 'affine' in kwargs: affine = kwargs.pop('affine') transform = guard_transform(affine) # If there is no currently active GDAL/AWS environment, create one. defenv() # Get AWS credentials if we're attempting to access a raster # on S3. pth, archive, scheme = parse_path(path) if scheme == 's3': Env().get_aws_credentials() log.debug("AWS credentials have been obtained") # Create dataset instances and pass the given env, which will # be taken over by the dataset's context manager if it is not # None. if mode == 'r': from rasterio._io import RasterReader s = RasterReader(path) elif mode == 'r+': from rasterio._io import writer s = writer(path, mode) elif mode == 'r-': from rasterio._base import DatasetReader s = DatasetReader(path) elif mode == 'w': from rasterio._io import writer s = writer(path, mode, driver=driver, width=width, height=height, count=count, crs=crs, transform=transform, dtype=dtype, nodata=nodata, **kwargs) else: raise ValueError( "mode string must be one of 'r', 'r+', or 'w', not %s" % mode) s.start() return s
def test_parse_path_file(): """Correctly parse an ordinary filesystem path""" assert parse_path('/foo.tif') == ('/foo.tif', None, '')
def open(fp, mode='r', driver=None, width=None, height=None, count=None, crs=None, transform=None, dtype=None, nodata=None, **kwargs): """Open a dataset for reading or writing. The dataset may be located in a local file, in a resource located by a URL, or contained within a stream of bytes. To access a dataset within a zip file without unzipping the archive use an Apache VFS style zip:// URL like zip://path/to/archive.zip!path/to/example.tif In read ('r') or read/write ('r+') mode, no other keyword arguments are required: the attributes are supplied by the opened dataset. In write mode, a driver name such as "GTiff" or "JPEG" (see GDAL docs or ``gdal_translate --help`` on the command line), ``width`` (number of pixels per line) and ``height`` (number of lines), the ``count`` number of bands in the new file must be specified. Additionally, the data type for bands such as ``rasterio.ubyte`` for 8-bit bands or ``rasterio.uint16`` for 16-bit bands must be specified using the ``dtype`` argument. Parameters ---------- fp: string or file A filename or URL, or file object opened in binary mode. mode: string "r" (read), "r+" (read/write), or "w" (write) driver: string Driver code specifying the format name (e.g. "GTiff" or "JPEG"). See GDAL docs at http://www.gdal.org/formats_list.html (optional, required for writing). width: int Number of pixels per line (optional, required for write). height: int Number of lines (optional, required for write). count: int > 0 Count of bands (optional, required for write). dtype: rasterio.dtype the data type for bands such as ``rasterio.ubyte`` for 8-bit bands or ``rasterio.uint16`` for 16-bit bands (optional, required for write) crs: dict or string Coordinate reference system (optional, recommended for write). transform: Affine instance Affine transformation mapping the pixel space to geographic space (optional, recommended for writing). nodata: number Defines pixel value to be interpreted as null/nodata (optional, recommended for write, will be broadcast to all bands). Returns ------- A ``DatasetReader`` or ``DatasetUpdater`` object. Notes ----- In write mode, you must specify at least ``width``, ``height``, ``count`` and ``dtype``. A coordinate reference system for raster datasets in write mode can be defined by the ``crs`` argument. It takes Proj4 style mappings like .. code:: {'proj': 'longlat', 'ellps': 'WGS84', 'datum': 'WGS84', 'no_defs': True} An affine transformation that maps ``col,row`` pixel coordinates to ``x,y`` coordinates in the coordinate reference system can be specified using the ``transform`` argument. The value should be an instance of ``affine.Affine`` .. code:: python >>> from affine import Affine >>> transform = Affine(0.5, 0.0, -180.0, 0.0, -0.5, 90.0) These coefficients are shown in the figure below. .. code:: | x | | a b c | | c | | y | = | d e f | | r | | 1 | | 0 0 1 | | 1 | a: rate of change of X with respect to increasing column, i.e. pixel width b: rotation, 0 if the raster is oriented "north up" c: X coordinate of the top left corner of the top left pixel d: rotation, 0 if the raster is oriented "north up" e: rate of change of Y with respect to increasing row, usually a negative number (i.e. -1 * pixel height) if north-up. f: Y coordinate of the top left corner of the top left pixel A 6-element sequence of the affine transformation matrix coefficients in ``c, a, b, f, d, e`` order, (i.e. GDAL geotransform order) will be accepted until 1.0 (deprecated). A virtual filesystem can be specified. The ``vfs`` parameter may be an Apache Commons VFS style string beginning with "zip://" or "tar://"". In this case, the ``path`` must be an absolute path within that container. """ if not isinstance(fp, string_types): if not (hasattr(fp, 'read') or hasattr(fp, 'write')): raise TypeError("invalid path or file: {0!r}".format(fp)) if mode and not isinstance(mode, string_types): raise TypeError("invalid mode: {0!r}".format(mode)) if driver and not isinstance(driver, string_types): raise TypeError("invalid driver: {0!r}".format(driver)) if dtype and not check_dtype(dtype): raise TypeError("invalid dtype: {0!r}".format(dtype)) if nodata is not None: nodata = float(nodata) if 'affine' in kwargs: # DeprecationWarning's are ignored by default with warnings.catch_warnings(): warnings.warn( "The 'affine' kwarg in rasterio.open() is deprecated at 1.0 " "and only remains to ease the transition. Please switch to " "the 'transform' kwarg. See " "https://github.com/mapbox/rasterio/issues/86 for details.", DeprecationWarning, stacklevel=2) if transform: warnings.warn( "Found both 'affine' and 'transform' in rasterio.open() - " "choosing 'transform'") transform = transform else: transform = kwargs.pop('affine') if transform: transform = guard_transform(transform) # Check driver/mode blacklist. if driver and is_blacklisted(driver, mode): raise RasterioIOError("Blacklisted: file cannot be opened by " "driver '{0}' in '{1}' mode".format( driver, mode)) # Special case for file object argument. if mode == 'r' and hasattr(fp, 'read'): @contextmanager def fp_reader(fp): memfile = MemoryFile(fp.read()) dataset = memfile.open() try: yield dataset finally: dataset.close() memfile.close() return fp_reader(fp) elif mode == 'w' and hasattr(fp, 'write'): @contextmanager def fp_writer(fp): memfile = MemoryFile() dataset = memfile.open(driver=driver, width=width, height=height, count=count, crs=crs, transform=transform, dtype=dtype, nodata=nodata, **kwargs) try: yield dataset finally: dataset.close() memfile.seek(0) fp.write(memfile.read()) memfile.close() return fp_writer(fp) else: # The 'normal' filename or URL path. _, _, scheme = parse_path(fp) with Env() as env: # Get AWS credentials only if we're attempting to access a # raster using the S3 scheme. if scheme == 's3': env.get_aws_credentials() log.debug("AWS credentials have been obtained") # Create dataset instances and pass the given env, which will # be taken over by the dataset's context manager if it is not # None. if mode == 'r': s = DatasetReader(fp) elif mode == 'r-': warnings.warn("'r-' mode is deprecated, use 'r'", DeprecationWarning) s = DatasetReader(fp) elif mode == 'r+': s = get_writer_for_path(fp)(fp, mode) elif mode == 'w': s = get_writer_for_driver(driver)(fp, mode, driver=driver, width=width, height=height, count=count, crs=crs, transform=transform, dtype=dtype, nodata=nodata, **kwargs) else: raise ValueError( "mode must be one of 'r', 'r+', or 'w', not %s" % mode) s.start() return s
def test_parse_gdal(): """GDAL dataset identifiers fall through properly""" assert parse_path('GDAL:filepath:varname') == ( 'GDAL:filepath:varname', None, None)
def open(fp, mode='r', driver=None, width=None, height=None, count=None, crs=None, transform=None, dtype=None, nodata=None, sharing=True, **kwargs): """Open a dataset for reading or writing. The dataset may be located in a local file, in a resource located by a URL, or contained within a stream of bytes. In read ('r') or read/write ('r+') mode, no keyword arguments are required: these attributes are supplied by the opened dataset. In write ('w' or 'w+') mode, the driver, width, height, count, and dtype keywords are strictly required. Parameters ---------- fp : str, file object or pathlib.Path object A filename or URL, a file object opened in binary ('rb') mode, or a Path object. mode : str, optional 'r' (read, the default), 'r+' (read/write), 'w' (write), or 'w+' (write/read). driver : str, optional A short format driver name (e.g. "GTiff" or "JPEG") or a list of such names (see GDAL docs at http://www.gdal.org/formats_list.html). In 'w' or 'w+' modes a single name is required. In 'r' or 'r+' modes the driver can usually be omitted. Registered drivers will be tried sequentially until a match is found. When multiple drivers are available for a format such as JPEG2000, one of them can be selected by using this keyword argument. width, height : int, optional The numbers of rows and columns of the raster dataset. Required in 'w' or 'w+' modes, they are ignored in 'r' or 'r+' modes. count : int, optional The count of dataset bands. Required in 'w' or 'w+' modes, it is ignored in 'r' or 'r+' modes. dtype : str or numpy dtype The data type for bands. For example: 'uint8' or ``rasterio.uint16``. Required in 'w' or 'w+' modes, it is ignored in 'r' or 'r+' modes. crs : str, dict, or CRS; optional The coordinate reference system. Required in 'w' or 'w+' modes, it is ignored in 'r' or 'r+' modes. transform : Affine instance, optional Affine transformation mapping the pixel space to geographic space. Required in 'w' or 'w+' modes, it is ignored in 'r' or 'r+' modes. nodata : int, float, or nan; optional Defines the pixel value to be interpreted as not valid data. Required in 'w' or 'w+' modes, it is ignored in 'r' or 'r+' modes. sharing : bool A flag that allows sharing of dataset handles. Default is `True`. Should be set to `False` in a multithreaded:w program. kwargs : optional These are passed to format drivers as directives for creating or interpreting datasets. For example: in 'w' or 'w+' modes a `tiled=True` keyword argument will direct the GeoTIFF format driver to create a tiled, rather than striped, TIFF. Returns ------- A ``DatasetReader`` or ``DatasetUpdater`` object. Examples -------- To open a GeoTIFF for reading using standard driver discovery and no directives: >>> import rasterio >>> with rasterio.open('example.tif') as dataset: ... print(dataset.profile) To open a JPEG2000 using only the JP2OpenJPEG driver: >>> with rasterio.open( ... 'example.jp2', driver='JP2OpenJPEG') as dataset: ... print(dataset.profile) To create a new 8-band, 16-bit unsigned, tiled, and LZW-compressed GeoTIFF with a global extent and 0.5 degree resolution: >>> from rasterio.transform import from_origin >>> with rasterio.open( ... 'example.tif', 'w', driver='GTiff', dtype='uint16', ... width=720, height=360, count=8, crs='EPSG:4326', ... transform=from_origin(-180.0, 90.0, 0.5, 0.5), ... nodata=0, tiled=True, compress='lzw') as dataset: ... dataset.write(...) """ if not isinstance(fp, string_types): if not (hasattr(fp, 'read') or hasattr(fp, 'write') or isinstance(fp, Path)): raise TypeError("invalid path or file: {0!r}".format(fp)) if mode and not isinstance(mode, string_types): raise TypeError("invalid mode: {0!r}".format(mode)) if driver and not isinstance(driver, string_types): raise TypeError("invalid driver: {0!r}".format(driver)) if dtype and not check_dtype(dtype): raise TypeError("invalid dtype: {0!r}".format(dtype)) if nodata is not None: nodata = float(nodata) if transform: transform = guard_transform(transform) # Check driver/mode blacklist. if driver and is_blacklisted(driver, mode): raise RasterioIOError( "Blacklisted: file cannot be opened by " "driver '{0}' in '{1}' mode".format(driver, mode)) # Special case for file object argument. if mode == 'r' and hasattr(fp, 'read'): @contextmanager def fp_reader(fp): memfile = MemoryFile(fp.read()) dataset = memfile.open() try: yield dataset finally: dataset.close() memfile.close() return fp_reader(fp) elif mode in ('w', 'w+') and hasattr(fp, 'write'): @contextmanager def fp_writer(fp): memfile = MemoryFile() dataset = memfile.open(driver=driver, width=width, height=height, count=count, crs=crs, transform=transform, dtype=dtype, nodata=nodata, **kwargs) try: yield dataset finally: dataset.close() memfile.seek(0) fp.write(memfile.read()) memfile.close() return fp_writer(fp) else: # If a pathlib.Path instance is given, convert it to a string path. if isinstance(fp, Path): fp = str(fp) # The 'normal' filename or URL path. _, _, scheme = parse_path(fp) with Env() as env: if scheme == 's3': env.credentialize() # Create dataset instances and pass the given env, which will # be taken over by the dataset's context manager if it is not # None. if mode == 'r': s = DatasetReader(fp, driver=driver, **kwargs) elif mode == 'r+': s = get_writer_for_path(fp)(fp, mode, driver=driver, **kwargs) elif mode.startswith("w"): s = get_writer_for_driver(driver)(fp, mode, driver=driver, width=width, height=height, count=count, crs=crs, transform=transform, dtype=dtype, nodata=nodata, **kwargs) else: raise ValueError( "mode must be one of 'r', 'r+', or 'w', not %s" % mode) return s
def test_parse_netcdf(): """Annoying URI-like GDAL dataset names fall through properly""" assert parse_path('NETCDF:filepath:varname') == ( 'NETCDF:filepath:varname', None, None)
def test_parse_path_vsi(): """Warn deprecation of old parse_path""" with pytest.warns(RasterioDeprecationWarning): assert parse_path('/vsifoo/bar.tif') == ('/vsifoo/bar.tif', None, None)
def test_parse_path_file(): """Correctly parse an ordinary filesystem path""" assert parse_path('/foo.tif') == ( '/foo.tif', None, '')
def test_parse_unknown_scheme(): """Raise exception for unknown WFS scheme""" with pytest.raises(ValueError): parse_path('gopher://foo.tif')
def test_parse_path_accept_get_params(): # See https://github.com/mapbox/rasterio/issues/1121 assert parse_path('http://example.com/index?a=1') == ( 'example.com/index?a=1', None, 'http')
def test_parse_path_with_vfs(): """Correctly parse path with legacy vfs parameter""" assert parse_path( 'foo.tif', vfs='zip://tests/data/files.zip') == ('foo.tif', 'tests/data/files.zip', 'zip')
def test_parse_unknown_scheme(): """Raise exception for unknown WFS scheme""" with pytest.raises(ValueError): parse_path('http://foo.tif')
def test_parse_path_file_scheme(): """Correctly parse file:// URL""" assert parse_path('file://foo.tif') == ('foo.tif', None, 'file')
def open(fp, mode='r', driver=None, width=None, height=None, count=None, crs=None, transform=None, dtype=None, nodata=None, **kwargs): """Open a dataset for reading or writing. The dataset may be located in a local file, in a resource located by a URL, or contained within a stream of bytes. In read ('r') or read/write ('r+') mode, no keyword arguments are required: these attributes are supplied by the opened dataset. In write ('w') mode, the driver, width, height, count, and dtype keywords are strictly required. Parameters ---------- fp : str or file object A filename or URL, or file object opened in binary ('rb') mode mode : str, optional 'r' (read, the default), 'r+' (read/write), or 'w' (write) driver : str, optional A short format driver name (e.g. "GTiff" or "JPEG") or a list of such names (see GDAL docs at http://www.gdal.org/formats_list.html). In 'w' mode a single name is required. In 'r' or 'r+' mode the driver can usually be omitted. Registered drivers will be tried sequentially until a match is found. When multiple drivers are available for a format such as JPEG2000, one of them can be selected by using this keyword argument. width, height : int, optional The numbers of rows and columns of the raster dataset. Required in 'w' mode, they are ignored in 'r' or 'r+' mode. count : int, optional The count of dataset bands. Required in 'w' mode, it is ignored in 'r' or 'r+' mode. dtype : str or numpy dtype The data type for bands. For example: 'uint8' or ``rasterio.uint16``. Required in 'w' mode, it is ignored in 'r' or 'r+' mode. crs : str, dict, or CRS; optional The coordinate reference system. Required in 'w' mode, it is ignored in 'r' or 'r+' mode. transform : Affine instance, optional Affine transformation mapping the pixel space to geographic space. Required in 'w' mode, it is ignored in 'r' or 'r+' mode. nodata : int, float, or nan; optional Defines the pixel value to be interpreted as not valid data. Required in 'w' mode, it is ignored in 'r' or 'r+' mode. kwargs : optional These are passed to format drivers as directives for creating or interpreting datasets. For example: in 'w' a `tiled=True` keyword argument will direct the GeoTIFF format driver to create a tiled, rather than striped, TIFF. Returns ------- A ``DatasetReader`` or ``DatasetUpdater`` object. Examples -------- To open a GeoTIFF for reading using standard driver discovery and no directives: >>> import rasterio >>> with rasterio.open('example.tif') as dataset: ... print(dataset.profile) To open a JPEG2000 using only the JP2OpenJPEG driver: >>> with rasterio.open( ... 'example.jp2', driver='JP2OpenJPEG') as dataset: ... print(dataset.profile) To create a new 8-band, 16-bit unsigned, tiled, and LZW-compressed GeoTIFF with a global extent and 0.5 degree resolution: >>> from rasterio.transform import from_origin >>> with rasterio.open( ... 'example.tif', 'w', driver='GTiff', dtype='uint16', ... width=720, height=360, count=8, crs='EPSG:4326', ... transform=from_origin(-180.0, 90.0, 0.5, 0.5), ... nodata=0, tiled=True, compress='lzw') as dataset: ... dataset.write(...) """ if not isinstance(fp, string_types): if not (hasattr(fp, 'read') or hasattr(fp, 'write')): raise TypeError("invalid path or file: {0!r}".format(fp)) if mode and not isinstance(mode, string_types): raise TypeError("invalid mode: {0!r}".format(mode)) if driver and not isinstance(driver, string_types): raise TypeError("invalid driver: {0!r}".format(driver)) if dtype and not check_dtype(dtype): raise TypeError("invalid dtype: {0!r}".format(dtype)) if nodata is not None: nodata = float(nodata) if 'affine' in kwargs: # DeprecationWarning's are ignored by default with warnings.catch_warnings(): warnings.warn( "The 'affine' kwarg in rasterio.open() is deprecated at 1.0 " "and only remains to ease the transition. Please switch to " "the 'transform' kwarg. See " "https://github.com/mapbox/rasterio/issues/86 for details.", DeprecationWarning, stacklevel=2) if transform: warnings.warn( "Found both 'affine' and 'transform' in rasterio.open() - " "choosing 'transform'") transform = transform else: transform = kwargs.pop('affine') if transform: transform = guard_transform(transform) # Check driver/mode blacklist. if driver and is_blacklisted(driver, mode): raise RasterioIOError( "Blacklisted: file cannot be opened by " "driver '{0}' in '{1}' mode".format(driver, mode)) # Special case for file object argument. if mode == 'r' and hasattr(fp, 'read'): @contextmanager def fp_reader(fp): memfile = MemoryFile(fp.read()) dataset = memfile.open() try: yield dataset finally: dataset.close() memfile.close() return fp_reader(fp) elif mode == 'w' and hasattr(fp, 'write'): @contextmanager def fp_writer(fp): memfile = MemoryFile() dataset = memfile.open(driver=driver, width=width, height=height, count=count, crs=crs, transform=transform, dtype=dtype, nodata=nodata, **kwargs) try: yield dataset finally: dataset.close() memfile.seek(0) fp.write(memfile.read()) memfile.close() return fp_writer(fp) else: # The 'normal' filename or URL path. _, _, scheme = parse_path(fp) with Env() as env: if scheme == 's3': env.credentialize() # Create dataset instances and pass the given env, which will # be taken over by the dataset's context manager if it is not # None. if mode == 'r': s = DatasetReader(fp, driver=driver, **kwargs) elif mode == 'r-': warnings.warn("'r-' mode is deprecated, use 'r'", DeprecationWarning) s = DatasetReader(fp) elif mode == 'r+': s = get_writer_for_path(fp)(fp, mode, driver=driver, **kwargs) elif mode == 'w': s = get_writer_for_driver(driver)(fp, mode, driver=driver, width=width, height=height, count=count, crs=crs, transform=transform, dtype=dtype, nodata=nodata, **kwargs) else: raise ValueError( "mode must be one of 'r', 'r+', or 'w', not %s" % mode) return s
def test_parse_netcdf(): """Annoying URI-like GDAL dataset names fall through properly""" assert parse_path('NETCDF:filepath:varname') == ('NETCDF:filepath:varname', None, None)
def test_parse_path_with_vfs(): """Correctly parse path with legacy vfs parameter""" assert parse_path('foo.tif', vfs='zip://tests/data/files.zip') == ( 'foo.tif', 'tests/data/files.zip', 'zip')
def open(fp, mode='r', driver=None, width=None, height=None, count=None, crs=None, transform=None, dtype=None, nodata=None, **kwargs): """Open a dataset for reading or writing. The dataset may be located in a local file, in a resource located by a URL, or contained within a stream of bytes. To access a dataset within a zip file without unzipping the archive use an Apache VFS style zip:// URL like zip://path/to/archive.zip!path/to/example.tif In read ('r') or read/write ('r+') mode, no other keyword arguments are required: the attributes are supplied by the opened dataset. In write mode, a driver name such as "GTiff" or "JPEG" (see GDAL docs or ``gdal_translate --help`` on the command line), ``width`` (number of pixels per line) and ``height`` (number of lines), the ``count`` number of bands in the new file must be specified. Additionally, the data type for bands such as ``rasterio.ubyte`` for 8-bit bands or ``rasterio.uint16`` for 16-bit bands must be specified using the ``dtype`` argument. Parameters ---------- fp: string or file A filename or URL, or file object opened in binary mode. mode: string "r" (read), "r+" (read/write), or "w" (write) driver: string Driver code specifying the format name (e.g. "GTiff" or "JPEG"). See GDAL docs at http://www.gdal.org/formats_list.html (optional, required for writing). width: int Number of pixels per line (optional, required for write). height: int Number of lines (optional, required for write). count: int > 0 Count of bands (optional, required for write). dtype: rasterio.dtype the data type for bands such as ``rasterio.ubyte`` for 8-bit bands or ``rasterio.uint16`` for 16-bit bands (optional, required for write) crs: dict or string Coordinate reference system (optional, recommended for write). transform: Affine instance Affine transformation mapping the pixel space to geographic space (optional, recommended for writing). nodata: number Defines pixel value to be interpreted as null/nodata (optional, recommended for write, will be broadcast to all bands). Returns ------- A ``DatasetReader`` or ``DatasetUpdater`` object. Notes ----- In write mode, you must specify at least ``width``, ``height``, ``count`` and ``dtype``. A coordinate reference system for raster datasets in write mode can be defined by the ``crs`` argument. It takes Proj4 style mappings like .. code:: {'proj': 'longlat', 'ellps': 'WGS84', 'datum': 'WGS84', 'no_defs': True} An affine transformation that maps ``col,row`` pixel coordinates to ``x,y`` coordinates in the coordinate reference system can be specified using the ``transform`` argument. The value should be an instance of ``affine.Affine`` .. code:: python >>> from affine import Affine >>> transform = Affine(0.5, 0.0, -180.0, 0.0, -0.5, 90.0) These coefficients are shown in the figure below. .. code:: | x | | a b c | | c | | y | = | d e f | | r | | 1 | | 0 0 1 | | 1 | a: rate of change of X with respect to increasing column, i.e. pixel width b: rotation, 0 if the raster is oriented "north up" c: X coordinate of the top left corner of the top left pixel d: rotation, 0 if the raster is oriented "north up" e: rate of change of Y with respect to increasing row, usually a negative number (i.e. -1 * pixel height) if north-up. f: Y coordinate of the top left corner of the top left pixel A 6-element sequence of the affine transformation matrix coefficients in ``c, a, b, f, d, e`` order, (i.e. GDAL geotransform order) will be accepted until 1.0 (deprecated). A virtual filesystem can be specified. The ``vfs`` parameter may be an Apache Commons VFS style string beginning with "zip://" or "tar://"". In this case, the ``path`` must be an absolute path within that container. """ if not isinstance(fp, string_types): if not (hasattr(fp, 'read') or hasattr(fp, 'write')): raise TypeError("invalid path or file: {0!r}".format(fp)) if mode and not isinstance(mode, string_types): raise TypeError("invalid mode: {0!r}".format(mode)) if driver and not isinstance(driver, string_types): raise TypeError("invalid driver: {0!r}".format(driver)) if dtype and not check_dtype(dtype): raise TypeError("invalid dtype: {0!r}".format(dtype)) if nodata is not None: nodata = float(nodata) if 'affine' in kwargs: # DeprecationWarning's are ignored by default with warnings.catch_warnings(): warnings.warn( "The 'affine' kwarg in rasterio.open() is deprecated at 1.0 " "and only remains to ease the transition. Please switch to " "the 'transform' kwarg. See " "https://github.com/mapbox/rasterio/issues/86 for details.", DeprecationWarning, stacklevel=2) if transform: warnings.warn( "Found both 'affine' and 'transform' in rasterio.open() - " "choosing 'transform'") transform = transform else: transform = kwargs.pop('affine') if transform: transform = guard_transform(transform) # Check driver/mode blacklist. if driver and is_blacklisted(driver, mode): raise RasterioIOError( "Blacklisted: file cannot be opened by " "driver '{0}' in '{1}' mode".format(driver, mode)) # Special case for file object argument. if mode == 'r' and hasattr(fp, 'read'): @contextmanager def fp_reader(fp): memfile = MemoryFile(fp.read()) dataset = memfile.open() try: yield dataset finally: dataset.close() memfile.close() return fp_reader(fp) elif mode == 'w' and hasattr(fp, 'write'): @contextmanager def fp_writer(fp): memfile = MemoryFile() dataset = memfile.open(driver=driver, width=width, height=height, count=count, crs=crs, transform=transform, dtype=dtype, nodata=nodata, **kwargs) try: yield dataset finally: dataset.close() memfile.seek(0) fp.write(memfile.read()) memfile.close() return fp_writer(fp) else: # The 'normal' filename or URL path. _, _, scheme = parse_path(fp) with Env() as env: # Get AWS credentials only if we're attempting to access a # raster using the S3 scheme. if scheme == 's3': env.get_aws_credentials() log.debug("AWS credentials have been obtained") # Create dataset instances and pass the given env, which will # be taken over by the dataset's context manager if it is not # None. if mode == 'r': s = DatasetReader(fp) elif mode == 'r-': warnings.warn("'r-' mode is deprecated, use 'r'", DeprecationWarning) s = DatasetReader(fp) elif mode == 'r+': s = get_writer_for_path(fp)(fp, mode) elif mode == 'w': s = get_writer_for_driver(driver)(fp, mode, driver=driver, width=width, height=height, count=count, crs=crs, transform=transform, dtype=dtype, nodata=nodata, **kwargs) else: raise ValueError( "mode must be one of 'r', 'r+', or 'w', not %s" % mode) return s
def open(path, mode='r', driver=None, width=None, height=None, count=None, crs=None, transform=None, dtype=None, nodata=None, **kwargs): """Open file at ``path`` in ``mode`` 'r' (read), 'r+' (read and write), or 'w' (write) and return a dataset Reader or Updater object. In write mode, a driver name such as "GTiff" or "JPEG" (see GDAL docs or ``gdal_translate --help`` on the command line), ``width`` (number of pixels per line) and ``height`` (number of lines), the ``count`` number of bands in the new file must be specified. Additionally, the data type for bands such as ``rasterio.ubyte`` for 8-bit bands or ``rasterio.uint16`` for 16-bit bands must be specified using the ``dtype`` argument. Parameters ---------- mode: string "r" (read), "r+" (read/write), or "w" (write) driver: string driver code specifying the format name (e.g. "GTiff" or "JPEG"). See GDAL docs at http://www.gdal.org/formats_list.html (optional, required for writing). width: int number of pixels per line (optional, required for write) height: int number of lines (optional, required for write) count: int > 0 number of bands (optional, required for write) dtype: rasterio.dtype the data type for bands such as ``rasterio.ubyte`` for 8-bit bands or ``rasterio.uint16`` for 16-bit bands (optional, required for write) crs: dict or string Coordinate reference system (optional, recommended for write) transform: Affine instance Affine transformation mapping the pixel space to geographic space (optional, recommended for writing). nodata: number Defines pixel value to be interpreted as null/nodata (optional, recommended for write) Returns ------- A ``DatasetReader`` or ``DatasetUpdater`` object. Notes ----- In write mode, you must specify at least ``width``, ``height``, ``count`` and ``dtype``. A coordinate reference system for raster datasets in write mode can be defined by the ``crs`` argument. It takes Proj4 style mappings like .. code:: {'proj': 'longlat', 'ellps': 'WGS84', 'datum': 'WGS84', 'no_defs': True} An affine transformation that maps ``col,row`` pixel coordinates to ``x,y`` coordinates in the coordinate reference system can be specified using the ``transform`` argument. The value should be an instance of ``affine.Affine`` .. code:: python >>> from affine import Affine >>> transform = Affine(0.5, 0.0, -180.0, 0.0, -0.5, 90.0) These coefficients are shown in the figure below. .. code:: | x | | a b c | | c | | y | = | d e f | | r | | 1 | | 0 0 1 | | 1 | a: rate of change of X with respect to increasing column, i.e. pixel width b: rotation, 0 if the raster is oriented "north up" c: X coordinate of the top left corner of the top left pixel d: rotation, 0 if the raster is oriented "north up" e: rate of change of Y with respect to increasing row, usually a negative number (i.e. -1 * pixel height) if north-up. f: Y coordinate of the top left corner of the top left pixel A 6-element sequence of the affine transformation matrix coefficients in ``c, a, b, f, d, e`` order, (i.e. GDAL geotransform order) will be accepted until 1.0 (deprecated). A virtual filesystem can be specified. The ``vfs`` parameter may be an Apache Commons VFS style string beginning with "zip://" or "tar://"". In this case, the ``path`` must be an absolute path within that container. """ if not isinstance(path, string_types): raise TypeError("invalid path: {0!r}".format(path)) if mode and not isinstance(mode, string_types): raise TypeError("invalid mode: {0!r}".format(mode)) if driver and not isinstance(driver, string_types): raise TypeError("invalid driver: {0!r}".format(driver)) if dtype and not check_dtype(dtype): raise TypeError("invalid dtype: {0!r}".format(dtype)) if transform: transform = guard_transform(transform) elif 'affine' in kwargs: affine = kwargs.pop('affine') transform = guard_transform(affine) # Get AWS credentials if we're attempting to access a raster # on S3. pth, archive, scheme = parse_path(path) if scheme == 's3': Env().get_aws_credentials() log.debug("AWS credentials have been obtained") # Create dataset instances and pass the given env, which will # be taken over by the dataset's context manager if it is not # None. if mode == 'r': from rasterio._io import RasterReader s = RasterReader(path) elif mode == 'r+': from rasterio._io import writer s = writer(path, mode) elif mode == 'r-': from rasterio._base import DatasetReader s = DatasetReader(path) elif mode == 'w': from rasterio._io import writer s = writer(path, mode, driver=driver, width=width, height=height, count=count, crs=crs, transform=transform, dtype=dtype, nodata=nodata, **kwargs) else: raise ValueError( "mode string must be one of 'r', 'r+', or 'w', not %s" % mode) s.start() return s