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 theinput_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, theinput_file
is resampled to the extent and resolution of themask_file
.- Pixel locations equal to
--maskval
in themask_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 contains0
values todstnodata
. - 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 use255
for byte data and-9999
for all others. - The
-i
/--invert
option behaves like the flag set bygdal_rasterize
. When set, it masks all values not inside a polygon. It's confusing, so use it carefully. - You can set
--of
, butrasterio
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 usegdal
, 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.