Skip to content

titan mask

A general-purpose masking utility. Handles reprojection and incompatible file size issues without complaining.

>>> titan mask --help

titan mask [-h] [-o OUTPUT_FILE] [--crop] [-m MASKVAL] [-i] [--at] [--dstnodata value]
           [--blocksize xsize ysize] [-r resampling] [--of raster_format]
           [--co creation_option [creation_option ...]] [--ram mb] input_file mask_file

Applies a no-data mask to a raster file. Supports raster and vector masking.

positional arguments:
  input_file            The raster file to mask.
  mask_file             The file to use as mask.

optional arguments:
  -h, --help            show this help message and exit
  -o OUTPUT_FILE, --output_file OUTPUT_FILE
                        Output masked file. Leave this blank to mask in-place.
  --crop                Crop output file to vector extent or to raster mask size/extent.
  -m MASKVAL, --maskval MASKVAL
                        [raster] Sets locations with this value to nodata. Uses the mask's nodata value by default
  -i, --invert          [vector] Mask areas outside of vector instead of inside.
  --at                  [vector] Mask all pixels touched by the vector.
  --dstnodata value     Output nodata value
  --blocksize xsize ysize
                        The raster processing block size.
  -r resampling         GDAL resampling option
  --of raster_format    GDAL driver format
  --co creation_option [creation_option ...]
                        GDAL creation option arguments
  --ram mb              The memory to allocate to a process (in mb).

This script simplifies cropping and masking raster data. It can mask with vector data (like subsetting a raster to an area of interest) and with raster data (like transferring nodata from one raster to another). It handles these varied approaches flexibly and, hopefully, intuitively. titan-apply-mask.py can:

  • Apply masks in-place, avoiding new file creation
  • Reproject vector data on-the-fly to match the raster's native projection
  • Reproject/resize raster data on-the-fly to handle files of inconsistent dimensions
  • Use either the mask file's nodata value or a user specified value for masking
  • Crop to match a mask file's spatial extent

This script mixes and matches gdal and rasterio based on the use case, and there may be some tricky behavior for users to navigate when it comes to setting parameters.

General guidelines

  • Set -o to force output file creation. If ignored, the mask will be applied in-place to the input_file. -o is required with --crop.
  • --crop will clip the output file to the extent of the mask file. For vector masks, the raster metadata is conserved (resolution, etc.). For raster masks, the input_file is resampled to the extent and resolution of the mask_file.
  • Pixel locations equal to --maskval in the mask_file will be masked in the output raster. So if you have a 0/1 mask, setting --maskval 0 will set all pixels where the mask contains 0 values to dstnodata.
  • Masked pixels will be assigned the value from --dstnodata. If not set explicitly, the raster's native nodata value will be used. If it doesn't have one, the default will be to use 255 for byte data and -9999 for all others.
  • The -i / --invert option behaves like the flag set by gdal_rasterize. When set, it masks all values not inside a polygon. It's confusing, so use it carefully.
  • You can set --of, but rasterio pretty much only writes geotiffs. Since we use rasterio for all raster masking operations, this means your driver options are very limited. Most of the vector masking operations use gdal, however, which allows writing many more driver formats.
  • --blocksize sets the tile size of the data processed in each iteration, using the input file's native block structure by default. It's most efficient to set a blocksize that is a multiple of the native blocksize: if a file is internally tiled with 256x256 blocks, setting --blocksize 512 512 or --blocksize 1024 1024 would use more memory but perform fewer I/O operations. If the input data aren't tiled, however, reading non-tiled then writing tiled data would be a bit slower. It would probably faster to set the blocksize as a multiple of the native blocksize (which is often size (1, ncols).

Vector Masking

Below are three use cases for masking with vector data.

Setting all values inside a vector to nodata

This is the simplest use case, which supports masking with Point, Line, Polygon and MultiPolygon features.

This is commonly used for burning values from polygon data into their location in a raster.

titan-apply-mask.py canopy-height-raster.tif lakes.shp --at

The above will burn nodata values into all canopy height pixel locations touched by the lakes.shp mask file.

Setting all values outside a vector to nodata

Another vector masking use case is to ignore all areas outside of a vector's footprint. This is useful if you want to focus on a specific area of interest, and handled with the -i flag.

titan-apply-mask.py west-coat-dem.tif california-state.shp -i

This would mask all areas outside of California in this west coast raster file. Which is great, but would ultimately create a large amount of nodata. Instead, it may be preferable to crop to the extent of the vector mask.

Cropping to a vector mask

It's often convenient to crop and mask data simultaneously to an area of interest. This is done with --crop.

titan-apply-mask.py california-canopy-cover.tif sonoma-county.shp --crop

This will crop the canopy cover dataset to the spatial extent of the Sonoma County vector and mask the pixels outside the polygon. All other raster metadata (resolution, etc.) is conserved.

While they perform similar functions—masking values outside of a polygon—--crop is mutually exclusive with -i, which cannot be set if --crop is used. I know this is confusing, but just let --crop do it's thing.

Raster Masking

Raster masking behaves similarly to vector masking.

When applying a mask in-place, titan-apply-mask.py reprojects the mask to the dimensions of the input file and updates the input nodata mask.

Setting --crop, which must be used in conjunction with -o, reprojects the input file to the dimensions of the mask before updating the input nodata mask.

In either case, beware of differences in spatial resolution when applying raster masks. You can tune how scale differences are handled using the -r flag, which controls how resampling is done. This is likely to have a minor effect, but should be considered where there are large differences in pixel sizes between input and mask files.