Skip to main content
A raster is a regular grid of numeric values with geo-referencing metadata that describes the location and resolution of the grid. Raster data is commonly used to represent terrain, elevation, and satellite imagery. WherobotsDB adds a raster column type to Apache Iceberg tables, so you can store and query raster data in tables. This tutorial describes how to use raster data type and raster functions in WherobotsDB for manipulating raster data.

In-DB raster vs. Out-DB raster

WherobotsDB supports two types of raster data: In-DB raster and Out-DB raster. In-DB raster stores the complete raster data in WherobotsDB. Out-DB rasters only holds the geo-referencing information of the raster, as well as the path to the actual raster data. The actual raster data is stored in remote storage, such as S3. Out-DB rasters are useful when the raster data is too large to be stored in parquet files, or when the raster data is already stored in some remote storage. In-DB and Out-DB Rasters In WherobotsDB, we recommend Out-DB raster for your raster data, as it is more efficient and scalable. In this tutorial, we will show you how to create an Out-DB raster table and an In-DB raster table. Out-DB rasters are fast for functions that read only the georeferencing information, such as RS_Metadata, RS_GeoReference, and RS_SRID. Functions that read band values, such as RS_Value, RS_MapAlgebra, and RS_Resample, must read the raster file from remote storage, so they run slower on out-DB rasters than on in-DB rasters. To speed up those reads, see Tune out-DB raster reads. Store only small rasters as in-DB rasters. In-DB rasters are stored in the table’s data files, so small ones, such as preprocessed chips, are read with high throughput by downstream applications, including machine learning tasks powered by RasterFlow. For instance, the 64x64 labeled chips in the EuroSAT dataset load faster as in-DB rasters. Large in-DB rasters make processing prone to out-of-memory errors, because the entire raster is loaded into memory when it is read from the data files. Store large rasters as out-DB rasters so they are loaded lazily; tasks that require shuffles, such as repartitioning and sorting, also run faster on out-DB rasters.

Create an Out-DB Raster type column

Out-DB Rasters has the same data type with In-DB Rasters, they are all represented as the raster column type in tables and can be loaded as RasterUDT objects in Sedona. If user has a table containing a raster column, it can have both In-DB and Out-DB rasters in that column.

Load raster files with the raster data source

Use the raster data source to load raster files. It reads GeoTIFF and Arc Info ASCII Grid (.asc) files as out-db rasters, splits each file into tiles as it reads it, and spreads the tiles across the cluster.
This NAIP image is a GeoTIFF with 512 × 512 internal tiles, so it loads as 96 rows. Each row holds one tile as an out-db raster, with the tile coordinates x and y and the name of the source file:
For the options of the raster data source, see Loading raster using the raster loader.
The raster data source keeps the pixel values exactly as stored in the file. Set option("autoRescale", "true") to apply the GeoTIFF’s per-band scale and offset while reading. See Band values, scale, and offset.

Load whole files, directories, or a list of files

To load each file as one out-db raster instead of tiles, set retile to false. The EuroSAT sample files are small and aren’t internally tiled, so the examples in the rest of this section load them this way:
A path that ends with / loads every .tif and .tiff file under that directory, including its subdirectories:
To load specific files, pass their paths:

Retrieve the path of Out-DB Rasters

The rasters path of out-db rasters can be retrieved using RS_BandPath function. It will give the path of the raster file in remote storage. If the argument is an in-db raster, RS_BandPath will return NULL.

Divide and explode Out-DB Rasters

The raster data source tiles files as it loads them. To split rasters loaded with retile set to false, such as df above, into tiles, use the RS_TileExplode function:
The rasters RS_TileExplode produces are also Out-DB rasters as long as the input raster is an Out-DB raster. These tiles reference different parts of the same raster file in remote storage, so they are very cheap to create.

Load out-db rasters from a STAC catalog

The STAC reader returns one row for each STAC item and adds an out-db raster to each asset, in assets['<asset name>'].rast, so the rasters of a STAC catalog need no separate loading step. The following example reads two items of the Sentinel-2 Collection 1 Level-2A collection on Earth Search and selects the raster of each item’s red asset:
Rasters generated by the STAC reader apply the GeoTIFF’s per-band scale and offset by default. See Band values, scale, and offset. To write the rasters to a table, see Raster Tables.

Supported Out-DB Storages

WherobotsDB supports out-db rasters on any storage that Hadoop supports, as long as the storage has an implementation of org.apache.hadoop.fs.FileSystem on the classpath of the Wherobots Cloud. In the above examples, we accessed out-db rasters stored on S3 using the S3A file system provided by Hadoop AWS. Following is a list of storages that are tested on Wherobots Cloud:

Create an In-DB Raster type column

All raster operations in Spatial SQL require Raster type objects. Therefore, this should be the next step after loading the data.

Load binary raster data

Assume we have a single raster data file called rasterData.tiff, at Path. Use the following code to load the data and create a WherobotsDB Dataframe.
The output will look like this:
For multiple raster data files use the following code to load the data from path and create raw DataFrame.
The above code works too for loading multiple raster data files. if the raster files are in separate directories and the option also makes sure that only .tif or .tiff files are being loaded.
The output will look like this:
The content column in the raster table is still in the raw form, binary form.
Recursive file lookup will also work similarly for raster datasets in .asc file formats.

From Geotiff

To verify this, use the following code to print the schema of the DataFrame:
The output will be like this:

From Arc Grid

The raster data is loaded the same way as tiff file, but the raster data is stored with the extension .asc, ASCII format. The following code creates a Raster type objects from binary data:

Raster’s metadata

WherobotsDB has a function to get the metadata for the raster, and also a function to get the world file of the raster.

Metadata

This function will return an array of metadata, it will have all the necessary information about the raster, Please refer to RS_MetaData.
Output for the following function will be:
The first two elements of the array represent the real-world geographic coordinates (like longitude/latitude) of the raster image’s top left pixel, while the next two elements represent the pixel dimensions of the raster.

World File

There are two kinds of georeferences, GDAL and ESRI seen in world files. For more information please refer to RS_GeoReference.
The Output will be as follows:
World files are used to georeference and geolocate images by establishing an image-to-world coordinate transformation that assigns real-world geographic coordinates to the pixels of the image.

Tune out-DB raster reads

Functions that read band values fetch out-DB raster data from remote storage. WherobotsDB caches those reads, and the parameters below control the cache. Set them when you create the Spark session; they can’t be changed afterward. For defaults and the full list, see Raster parameters.

Out-DB raster cache

If an out-DB raster is read from the same path more than once, it may hit the cache instead of being fetched from remote storage again. The cache is per executor core: cores in the same executor don’t share a cache, because it is implemented as thread-local variables. spark.wherobots.raster.outdb.pool.size sets the number of rasters in each cache (default 100). When a cache is full, the least recently used raster is evicted. The cache is stored on local disk, in the directory set by spark.wherobots.raster.outdb.cache.dir (default /data/outdb-cache), which is also where the Spark block manager stores shuffled data. If disk space runs short, lower the pool size or use a larger EBS volume. If your out-DB rasters are rarely read more than once, set the pool size to 0 to disable the cache.
The pool size should be larger than the number of distinct out-DB raster paths in each partition. Otherwise, the cache thrashes and won’t be effective.

Read-ahead size

The cache doesn’t download an entire out-DB raster at once. It caches only the parts of the raster file that are read. For example, RS_Value(rast, pt) fetches and caches only the part of the file that contains the tile with pt. spark.wherobots.raster.outdb.readahead sets the size of each read (default 64k):
  • For functions that read the entire raster file, such as RS_MapAlgebra and RS_Count, a larger read-ahead size, for example 4m, improves performance.
  • For functions that read a small portion of the raster file, such as RS_Value, a smaller read-ahead size performs better, because the extra data read ahead isn’t reused. The exception is many RS_Value calls that together hit most of the tiles of an out-DB raster: the extra data is then reused by later calls, so a larger read-ahead size helps.

Improve the cache hit rate

Because each executor core has its own cache, a raster read on different cores is cached more than once. Two practices make cache hits more likely. In both examples, RS_TileExplode splits the 13-band EuroSAT sample files into 32x32 out-DB tiles, and RS_MapAlgebra combines the first two bands of each tile. Cache the DataFrame. Cache the DataFrame that contains out-DB rasters before running raster operations on it. Spark is then more likely to schedule the operations on the same executor cores, so cached rasters are reused.
Sort by raster path. Out-DB rasters that reference the same remote file hit the cache more often when they are adjacent. For a tiled out-DB raster dataset, sort the rasters by RS_BandPath(rast) before processing. The performance gain usually outweighs the cost of the sort.

Use Cloud Optimized GeoTIFF

Use Cloud Optimized GeoTIFF (COG) files for out-DB rasters. COG is optimized for reading from remote storage such as S3:
  1. A COG keeps its Image File Directory (IFD) in a contiguous block at the beginning of the file, so WherobotsDB reads the entire IFD without seeking to discrete locations in the file. This matters for remote storage, where many small discrete reads are much slower than a single large read.
  2. A COG organizes band data in properly sized square tiles, such as 256x256. Square tiles are more likely than strip tiles, such as 10000x1, to be reused by most raster operations, especially RS_Tile and RS_TileExplode. WherobotsDB also reads GeoTIFFs with strip tiles, but performance may be worse than with COG files.
To inspect the tile size of a GeoTIFF file, run gdalinfo and look at the Band 1 section of the output. The tile size is 256x256 in this example:
To convert a GeoTIFF file to COG, use gdal_translate with the COG output driver (-of COG):
You can also specify -co COMPRESS=DEFLATE or -co COMPRESS=LZW to set the compression method. See the GDAL COG documentation for more information.