njtierney / geotargets

Targets extensions for geospatial data
https://njtierney.github.io/geotargets/
Other
49 stars 4 forks source link

Add taget factory for splitting raster into tiles #76

Open Aariq opened 1 month ago

Aariq commented 1 month ago

I took a shot at creating a tar_terra_tiles() which is a target factory that creates three targets: 1) an upstream target that takes a SpatRaster and a template to define the tiles (the y argument of terra::makeTiles()), splits the raster into tiles, saves them to disk, and returns a vector of file paths. 2) a file target that maps over the file paths returned by makeTiles() using a target with format = "file" or "file_fast" 3) a downstream target that maps over the file paths and reads them in as rasters using dynamic branching.

This downstream target is a pattern that is ready to use in further targets with pattern = map() and starts to address #74.

This is heavily inspired by tarchetypes::tar_files()

The main downside to this pattern is that it basically duplicates the tiles on disk—once saved in a directory defined by the tiles_dir argument and again in the targets store when those files are read back in. Deleting those files would invalidate the files target, but not the upstream target that creates them, so I'm forced to have the upstream target always re-run with cue = tar_cue("always"). This is not ideal as making tiles is often a computationally expensive step. I've left #TODO comments with questions and aspirations about how this might work better and would love feedback.

Aariq commented 1 month ago

Note to self: clean up the tiles files on disk (not in _targets)? Either write them to a tempfile to begin with or add a final target to remove them? (but then won't the files target always be invalidated? hmm...)

Aariq commented 1 month ago

Ok, it is "working" now (not passing check, but there is a test that should work now to give you an idea of what it does). Here's what the manifest looks like:

library(targets)
tar_script({
    library(targets)
    library(geotargets)
    # devtools::load_all()
    library(terra)
    list(
        tar_target(
            my_file,
            system.file("ex/elev.tif", package="terra"),
            format = "file"
        ),
        tar_terra_rast(
            my_map,
            terra::rast(my_file)
        ),
        tar_terra_tiles(
            name = rast_split,
            raster = my_map,
            template = terra::rast(ncols = 2, nrows = 2),
            tiles_dir = "tiles_test"
        )
    )
})
targets::tar_manifest(callr_function = NULL)
#> terra 1.7.71
#> # A tibble: 5 × 3
#>   name             command                                               pattern
#>   <chr>            <chr>                                                 <chr>  
#> 1 my_file          "system.file(\"ex/elev.tif\", package = \"terra\")"   <NA>   
#> 2 my_map           "terra::rast(my_file)"                                <NA>   
#> 3 rast_split_tile  "geotargets:::make_tiles(raster = my_map, template =… <NA>   
#> 4 rast_split_files "rast_split_tile"                                     map(ra…
#> 5 rast_split       "rast(rast_split_files)"                              map(ra…

Created on 2024-05-24 with reprex v2.1.0

Aariq commented 1 week ago

Just pushed a fairly major improvement: