njtierney / geotargets

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

only allow `iteration = "list"` for terra targets #81

Open Aariq opened 3 weeks ago

Aariq commented 3 weeks ago

Only iteration = "list" seems to work for tar_terra_*(), so perhaps that should just be hard-coded.

Aariq commented 3 weeks ago

On the other hand, vctrs appears to be extensible, so we could look into exporting new vec_slice and vec_c S3 methods instead. That would allow for something like dynamically branched raster targets being combined into layers of a single SpatRaster automatically when iteration = "vector"

njtierney commented 2 weeks ago

so we could look into exporting new vec_slice and vec_c S3 methods instead

I've been keen to use vctrs in earnest, however I'm not sure how this would work for us as I can't right now think of how rasters could be represented as a vector?

My understanding is that we'd need to create new vctrs class for terra, in order to implement vec_slice and vec_c?

Although looking at the documentation for https://vctrs.r-lib.org/reference/vec_slice.html this works for data frames, but https://vctrs.r-lib.org/reference/vec_c.html is just for vectors.

Aariq commented 1 week ago

I'm thinking of dynamic branching e.g. where you create a tar_terra_rast() target with the map argument. The iteration argument must be set to "list" or you won't be able to read in the target with tar_read() and you won't be able to iterate over the result in subsequent targets.

targets::tar_script({
        library(targets)
        library(geotargets)
        library(terra)

        list(
            tar_target(
                to_add,
                c(1, 2, 3)
            ),
            tar_target(
                my_file,
                system.file("ex/elev.tif", package="terra"),
                format = "file"
            ),
            tar_terra_rast(
                my_map,
                terra::rast(my_file)
            ),
            tar_terra_rast(
                my_map_plus,
                my_map + to_add,
                pattern = to_add
            ),
            tar_terra_rast(
                my_map_plus_list,
                my_map + to_add,
                pattern = to_add,
                iteration = "list"
            )
        )
    })

    targets::tar_make()
#> terra 1.7.78
#> ▶ dispatched target my_file
#> ● completed target my_file [0.002 seconds]
#> ▶ dispatched target to_add
#> ● completed target to_add [0 seconds]
#> ▶ dispatched target my_map
#> ● completed target my_map [0.006 seconds]
#> ▶ dispatched branch my_map_plus_list_e98a12d3e3374380
#> ● completed branch my_map_plus_list_e98a12d3e3374380 [0.003 seconds]
#> ▶ dispatched branch my_map_plus_list_ba56ffbcd54ddba8
#> ● completed branch my_map_plus_list_ba56ffbcd54ddba8 [0.004 seconds]
#> ▶ dispatched branch my_map_plus_list_e5eb83559289f599
#> ● completed branch my_map_plus_list_e5eb83559289f599 [0.004 seconds]
#> ● completed pattern my_map_plus_list
#> ▶ dispatched branch my_map_plus_e98a12d3e3374380
#> ● completed branch my_map_plus_e98a12d3e3374380 [0.004 seconds]
#> ▶ dispatched branch my_map_plus_ba56ffbcd54ddba8
#> ● completed branch my_map_plus_ba56ffbcd54ddba8 [0.013 seconds]
#> ▶ dispatched branch my_map_plus_e5eb83559289f599
#> ● completed branch my_map_plus_e5eb83559289f599 [0.004 seconds]
#> ● completed pattern my_map_plus
#> ▶ ended pipeline [0.348 seconds]
    targets::tar_read(my_map_plus_list)
#> $my_map_plus_list_e98a12d3e3374380
#> class       : SpatRaster 
#> dimensions  : 90, 95, 1  (nrow, ncol, nlyr)
#> resolution  : 0.008333333, 0.008333333  (x, y)
#> extent      : 5.741667, 6.533333, 49.44167, 50.19167  (xmin, xmax, ymin, ymax)
#> coord. ref. : lon/lat WGS 84 (EPSG:4326) 
#> source      : my_map_plus_list_e98a12d3e3374380 
#> name        : elevation 
#> min value   :       142 
#> max value   :       548 
#> 
#> $my_map_plus_list_ba56ffbcd54ddba8
#> class       : SpatRaster 
#> dimensions  : 90, 95, 1  (nrow, ncol, nlyr)
#> resolution  : 0.008333333, 0.008333333  (x, y)
#> extent      : 5.741667, 6.533333, 49.44167, 50.19167  (xmin, xmax, ymin, ymax)
#> coord. ref. : lon/lat WGS 84 (EPSG:4326) 
#> source      : my_map_plus_list_ba56ffbcd54ddba8 
#> name        : elevation 
#> min value   :       143 
#> max value   :       549 
#> 
#> $my_map_plus_list_e5eb83559289f599
#> class       : SpatRaster 
#> dimensions  : 90, 95, 1  (nrow, ncol, nlyr)
#> resolution  : 0.008333333, 0.008333333  (x, y)
#> extent      : 5.741667, 6.533333, 49.44167, 50.19167  (xmin, xmax, ymin, ymax)
#> coord. ref. : lon/lat WGS 84 (EPSG:4326) 
#> source      : my_map_plus_list_e5eb83559289f599 
#> name        : elevation 
#> min value   :       144 
#> max value   :       550
    targets::tar_read(my_map_plus)
#> Error:
#> ! `my_map_plus_e98a12d3e3374380` must be a vector, not a <SpatRaster> object.

Created on 2024-07-22 with reprex v2.1.0

Played around with vctrs a bit and I don't think it's going to help here. E.g. to create a new kind of vector you'd use e.g. new_vctr(double()), but with a SpatRaster like vew_vctr(my_map) you get an error:

Error in `new_vctr()`:
! `.data` must be a vector type.

I could be missing something, but it seems like this is not really what vctrs is intended for. I'm going to submit a PR that hard-codes iteration = "list"