Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add taget factory for splitting raster into tiles #76

Merged
merged 27 commits into from
Jul 11, 2024
Merged

Conversation

Aariq
Copy link
Collaborator

@Aariq Aariq commented May 22, 2024

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 Aariq marked this pull request as draft May 22, 2024 00:40
@Aariq Aariq linked an issue May 22, 2024 that may be closed by this pull request
@Aariq
Copy link
Collaborator Author

Aariq commented May 24, 2024

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
Copy link
Collaborator Author

Aariq commented May 24, 2024

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 Aariq changed the title WIP: taget factory for splitting raster into tiles Add taget factory for splitting raster into tiles May 29, 2024
@Aariq Aariq marked this pull request as ready for review May 29, 2024 20:41
@Aariq Aariq requested a review from njtierney May 29, 2024 20:41
@Aariq
Copy link
Collaborator Author

Aariq commented Jun 28, 2024

Just pushed a fairly major improvement:

  • No longer requires writing out to files outside of _targets/
  • Now creates just two targets:
    • an upstream target that is a list of numeric vectors that can be coerced to SpatExtent objects
    • a downstream target that iterates over the list of numeric vectors using them to set the window() of the original raster
  • Exports two new helper functions, mostly so the command in tar_manifest() looks pretty, but also they might be helpful on their own.

Copy link
Owner

@njtierney njtierney left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just some small changes, this is looking really nice!

R/tar_terra_tiles.R Outdated Show resolved Hide resolved
#' @param gdal character. GDAL driver specific datasource creation options
#' passed to [terra::makeTiles()]
#'
#' @param ... additional arguments not yet used
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
#' @param ... additional arguments not yet used
#' @param ... additional arguments. Not yet used.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was for consistency with other functions ... arg and I think it is probably grammatically correct as is, although could be "additional arguments which are not yet used". Either way, I'll keep it as-is for now and if we want to change it we can change it for all functions in a separate PR.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yup that makes sense!

R/tar_terra_tiles.R Outdated Show resolved Hide resolved
R/tar_terra_tiles.R Outdated Show resolved Hide resolved
tests/testthat/test-tar_terra_tiles.R Outdated Show resolved Hide resolved
R/tar_terra_tiles.R Outdated Show resolved Hide resolved
R/tar_terra_tiles.R Outdated Show resolved Hide resolved
#' SpatRaster in place, returns a new SpatRaster leaving the original unchanged.
#'
#' @param raster A SpatRaster object
#' @param window A SpatExtent object
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
#' @param window A SpatExtent object
#' @param window A SpatExtent object. The window of interest.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I went with:

#' @param raster a SpatRaster object
#' @param window a SpatExtent object defining the area of interest

just because I like it when the @param descriptions can be a single phrase or sentence

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yup that reads great!

@Aariq Aariq requested a review from njtierney July 5, 2024 17:51
Copy link
Owner

@njtierney njtierney left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me!

@Aariq Aariq merged commit f8384b7 into master Jul 11, 2024
7 checks passed
@Aariq Aariq deleted the tar_terra_tiles branch July 19, 2024 16:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Best way to use SpatRaster tiles?
2 participants