Skip to content

Commit a1bcc2e

Browse files
pre-release sits 1.5.0 - passed tests
2 parents 2aaaa17 + 084f13d commit a1bcc2e

24 files changed

+232
-150
lines changed

NEWS.md

+18
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,23 @@
11
# SITS Release History
22

3+
# What's new in SITS version 1.5
4+
* Improved support for GPU-based classification of deep learning models
5+
* Support for Sentinel-1 GRD and RTC collections from Planetary Computer
6+
* Include parameter tile to select data from Sentinel-1 (MPC)
7+
* Include parameter tile to select data from Sentinel-2 (DEAFRICA)
8+
* Include parameter tile to select data from HLS collections
9+
* Support for non-normalized derived indexes
10+
* Support for shapefiles as ROI in `sits_cube()`
11+
* Fix inconsistencies in HLS scale factors
12+
* New function to obtain ROI based on MGRS tiles
13+
* Add support for uncertainty cubes in `sits_mosaic()`
14+
* Improve performance of `sits_segment()` using chunk parallelization
15+
* Include uncertainty measures for vector probability cubes
16+
* New `sits_clean()` function to improve classified maps
17+
* New functions `sits_sampling_design()` and `sits_stratified_sampling()`
18+
* New `sits_reduce()` function
19+
* Include `dtw` distance when building SOM maps
20+
321
# What's new in SITS version 1.4
422

523
### Hotfix version 1.4.2-3

R/api_block.R

+14
Original file line numberDiff line numberDiff line change
@@ -132,3 +132,17 @@ NULL
132132
x[["nrows"]] <- .as_int(value)
133133
x
134134
}
135+
136+
#' @title Regulate block size
137+
#'
138+
#' @description
139+
#' Terra requires at least two pixels to recognize an extent as valid
140+
#' polygon and not a line or point
141+
#'
142+
#' @noRd
143+
#' @param block A block.
144+
#' @returns A block with the size fixed
145+
.block_regulate_size <- function(block) {
146+
block[block == 1] <- 2
147+
block
148+
}

R/api_cube.R

+3-16
Original file line numberDiff line numberDiff line change
@@ -1241,6 +1241,9 @@ NULL
12411241
on.exit(suppressMessages(sf::sf_use_s2(s2_status)))
12421242
# Get block size of raster file
12431243
block <- .raster_file_blocksize(.raster_open_rast(.tile_path(cube)))
1244+
# Terra requires at least two pixels to recognize an extent as valid
1245+
# polygon and not a line or point
1246+
block <- .block_regulate_size(block)
12441247
cube_chunks <- slider::slide(cube, function(tile) {
12451248
chunks <- .tile_chunks_create(
12461249
tile = tile,
@@ -1266,19 +1269,3 @@ NULL
12661269
})
12671270
return(unlist(cube_chunks, recursive = FALSE))
12681271
}
1269-
1270-
# .cube_split_segments <- function(cube, block) {
1271-
# segments_sf <- .segments_read_vec(segments)
1272-
# chunks <- .tile_chunks_create(
1273-
# tile = segments,
1274-
# overlap = 0,
1275-
# block = block
1276-
# )
1277-
# chunks_sf <- .bbox_as_sf(
1278-
# .bbox(chunks, by_feature = TRUE), as_crs = sf::st_crs(segments_sf)
1279-
# )
1280-
# chunks_jobs <- slider::slide(chunks_sf[1,], function(chunk_sf) {
1281-
# segments_sf[ .intersects(segments_sf, chunk_sf),]
1282-
# })
1283-
# return(chunks_sf)
1284-
# }

R/api_regularize.R

-1
Original file line numberDiff line numberDiff line change
@@ -208,7 +208,6 @@
208208
default_crs = .crs(cube_crs),
209209
by_feature = TRUE
210210
))
211-
browser()
212211
file_info <- .fi(cube_crs)[.intersects({{fi_bbox}}, .x), ]
213212
.cube_create(
214213
source = .tile_source(cube_crs),

R/api_sf.R

+29-16
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,10 @@
99
#' @param start_date Start date for the data set.
1010
#' @param end_date End date for the data set.
1111
#' @param n_sam_pol Number of samples per polygon to be read.
12-
#' @param pol_id ID attribute for polygons shapefile.
12+
#' @param pol_id ID attribute which contains label
1313
#' (for POLYGON or MULTIPOLYGON shapefile).
14+
#' @param sampling_type Spatial sampling type: random, hexagonal,
15+
#' regular, or Fibonacci.
1416
#' @return A tibble with information the samples to be retrieved.
1517
#'
1618
.sf_get_samples <- function(sf_object,
@@ -19,7 +21,8 @@
1921
start_date,
2022
end_date,
2123
n_sam_pol,
22-
pol_id) {
24+
pol_id,
25+
sampling_type) {
2326
# Pre-condition - is the sf object has geometries?
2427
.check_that(
2528
x = nrow(sf_object) > 0,
@@ -44,6 +47,7 @@
4447
label = label,
4548
n_sam_pol = n_sam_pol,
4649
pol_id = pol_id,
50+
sampling_type = sampling_type,
4751
start_date = start_date,
4852
end_date = end_date
4953
)
@@ -60,22 +64,25 @@
6064
#' @description reads a shapefile and retrieves a sits tibble
6165
#' containing a set of lat/long points for data retrieval
6266
#'
63-
#' @param sf_object sf object .
64-
#' @param label_attr Attribute in sf object used as a polygon label.
65-
#' @param label Label to be assigned to points.
66-
#' @param n_sam_pol Number of samples per polygon to be read
67-
#' (for POLYGON or MULTIPOLYGON shapes).
68-
#' @param pol_id ID attribute for polygons.
69-
#' @param start_date Start of the interval for the time series
70-
#' in "YYYY-MM-DD" format (optional).
71-
#' @param end_date End of the interval for the time series in
72-
#' "YYYY-MM-DD" format (optional).
67+
#' @param sf_object sf object.
68+
#' @param label_attr Attribute in sf object used as a polygon label.
69+
#' @param label Label to be assigned to points.
70+
#' @param n_sam_pol Number of samples per polygon to be read
71+
#' (for POLYGON or MULTIPOLYGON shapes).
72+
#' @param pol_id ID attribute for polygons which contains the label
73+
#' @param sampling_type Spatial sampling type: random, hexagonal,
74+
#' regular, or Fibonacci.
75+
#' @param start_date Start of the interval for the time series
76+
#' in "YYYY-MM-DD" format (optional).
77+
#' @param end_date End of the interval for the time series in
78+
#' "YYYY-MM-DD" format (optional).
7379
#' @return A sits tibble with points to to be read.
7480
.sf_to_tibble <- function(sf_object,
7581
label_attr,
7682
label,
7783
n_sam_pol,
7884
pol_id,
85+
sampling_type,
7986
start_date,
8087
end_date) {
8188

@@ -110,7 +117,8 @@
110117
label_attr = label_attr,
111118
label = label,
112119
n_sam_pol = n_sam_pol,
113-
pol_id = pol_id
120+
pol_id = pol_id,
121+
sampling_type = sampling_type
114122
)
115123
)
116124

@@ -170,14 +178,17 @@
170178
#' @param label_attr Attribute in the shapefile used as a polygon label
171179
#' @param label Label to be assigned to points
172180
#' @param n_sam_pol Number of samples per polygon to be read
173-
#' @param pol_id ID attribute for polygons shapefile.
181+
#' @param pol_id ID attribute for polygons containing the label
182+
#' @param sampling_type Spatial sampling type: random, hexagonal,
183+
#' regular, or Fibonacci.
174184
#' @return A tibble with latitude/longitude points from POLYGON geometry
175185
#'
176186
.sf_polygon_to_tibble <- function(sf_object,
177187
label_attr,
178188
label,
179189
n_sam_pol,
180-
pol_id) {
190+
pol_id,
191+
sampling_type) {
181192
# get the db file
182193
sf_df <- sf::st_drop_geometry(sf_object)
183194

@@ -213,7 +224,9 @@
213224
polygon_id <- unname(as.character(sf_df[i, pol_id]))
214225
}
215226
# obtain a set of samples based on polygons
216-
points <- list(sf::st_sample(sf_object[i, ], size = n_sam_pol))
227+
points <- list(sf::st_sample(sf_object[i, ],
228+
type = sampling_type,
229+
size = n_sam_pol))
217230
# get one time series per sample
218231
pts_tab <- points |>
219232
purrr::pmap_dfr(function(p) {

R/api_shp.R

+7-3
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,11 @@
88
#' @param shp_attr Shapefile attribute that describes the label.
99
#' @param start_date Start date for the data set.
1010
#' @param end_date End date for the data set.
11-
#' @param .n_shp_pol Number of samples per polygon to be read.
12-
#' @param .shp_id ID attribute for polygons shapefile.
11+
#' @param n_shp_pol Number of samples per polygon to be read.
12+
#' @param shp_id ID attribute which contains the label
1313
#' (for POLYGON or MULTIPOLYGON shapefile).
14+
#' @param sampling_type Spatial sampling type: random, hexagonal,
15+
#' regular, or Fibonacci.
1416
#' @return A sits tibble with samples to be retrieved.
1517
#'
1618
.shp_get_samples <- function(shp_file,
@@ -19,7 +21,8 @@
1921
start_date,
2022
end_date,
2123
n_shp_pol,
22-
shp_id) {
24+
shp_id,
25+
sampling_type) {
2326
# Pre-condition - check the shape file and its attribute
2427
sf_shape <- .shp_transform_to_sf(
2528
shp_file = shp_file,
@@ -33,6 +36,7 @@
3336
label = label,
3437
n_sam_pol = n_shp_pol,
3538
pol_id = shp_id,
39+
sampling_type = sampling_type,
3640
start_date = start_date,
3741
end_date = end_date
3842
)

R/sits_classify.R

+6
Original file line numberDiff line numberDiff line change
@@ -287,6 +287,9 @@ sits_classify.raster_cube <- function(data,
287287
memsize = memsize,
288288
multicores = multicores
289289
)
290+
# Terra requires at least two pixels to recognize an extent as valid
291+
# polygon and not a line or point
292+
block <- .block_regulate_size(block)
290293
# Prepare parallel processing
291294
.parallel_start(
292295
workers = multicores, log = verbose,
@@ -443,6 +446,9 @@ sits_classify.segs_cube <- function(data,
443446
memsize = memsize,
444447
multicores = multicores
445448
)
449+
# Terra requires at least two pixels to recognize an extent as valid
450+
# polygon and not a line or point
451+
block <- .block_regulate_size(block)
446452
# Prepare parallel processing
447453
.parallel_start(
448454
workers = multicores, log = verbose,

R/sits_get_data.R

+9-2
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@
4747
#' @param pol_avg Logical: summarize samples for each polygon?
4848
#' @param pol_id ID attribute for polygons
4949
#' (character vector of length 1)
50+
#' @param sampling_type Spatial sampling type: random, hexagonal,
51+
#' regular, or Fibonacci.
5052
#' @param multicores Number of threads to process the time series
5153
#' (integer, with min = 1 and max = 2048).
5254
#' @param progress Logical: show progress bar?
@@ -106,6 +108,7 @@ sits_get_data <- function(cube,
106108
n_sam_pol = 30L,
107109
pol_avg = FALSE,
108110
pol_id = NULL,
111+
sampling_type = "random",
109112
multicores = 2L,
110113
progress = TRUE) {
111114
# Pre-conditions
@@ -161,6 +164,7 @@ sits_get_data.shp <- function(cube,
161164
n_sam_pol = 30,
162165
pol_avg = FALSE,
163166
pol_id = NULL,
167+
sampling_type = "random",
164168
multicores = 2,
165169
progress = FALSE) {
166170
# Pre-condition - shapefile should have an id parameter
@@ -179,7 +183,8 @@ sits_get_data.shp <- function(cube,
179183
start_date = start_date,
180184
end_date = end_date,
181185
n_shp_pol = n_sam_pol,
182-
shp_id = pol_id
186+
shp_id = pol_id,
187+
sampling_type = sampling_type
183188
)
184189
# Extract time series from a cube given a data.frame
185190
data <- .data_get_ts(
@@ -208,6 +213,7 @@ sits_get_data.sf <- function(cube,
208213
n_sam_pol = 30,
209214
pol_avg = FALSE,
210215
pol_id = NULL,
216+
sampling_type = "random",
211217
multicores = 2,
212218
progress = FALSE) {
213219
.check_that(
@@ -227,7 +233,8 @@ sits_get_data.sf <- function(cube,
227233
start_date = start_date,
228234
end_date = end_date,
229235
n_sam_pol = n_sam_pol,
230-
pol_id = pol_id
236+
pol_id = pol_id,
237+
sampling_type = sampling_type
231238
)
232239
# Extract time series from a cube given a data.frame
233240
data <- .data_get_ts(

R/sits_lighttae.R

+20-14
Original file line numberDiff line numberDiff line change
@@ -333,20 +333,26 @@ sits_lighttae <- function(samples = NULL,
333333
values <- array(
334334
data = as.matrix(values), dim = c(n_samples, n_times, n_bands)
335335
)
336-
# Transform to a torch dataset
337-
values <- .as_dataset(values)
338-
# We need to transform in a dataloader to use the batch size
339-
values <- torch::dataloader(
340-
values, batch_size = 2^15
341-
)
342-
# Do classification
343-
values <- .try(
344-
stats::predict(object = torch_model, values),
345-
.msg_error = paste("An error occured while transfering",
346-
"data to GPU. Please reduce the value of",
347-
"the `gpu_memory` parameter.")
348-
)
349-
# Convert to tensor cpu to support GPU processing
336+
# if CUDA is available, transform to torch data set
337+
# Load into GPU
338+
if (torch::cuda_is_available()) {
339+
values <- .as_dataset(values)
340+
# We need to transform in a dataloader to use the batch size
341+
values <- torch::dataloader(
342+
values, batch_size = 2^15
343+
)
344+
# Do GPU classification
345+
values <- .try(
346+
stats::predict(object = torch_model, values),
347+
.msg_error = paste("An error occured while transfering",
348+
"data to GPU. Please reduce the value of",
349+
"the `gpu_memory` parameter.")
350+
)
351+
} else{
352+
# Do CPU classification
353+
values <- stats::predict(object = torch_model, values)
354+
}
355+
# Convert to tensor CPU
350356
values <- torch::as_array(
351357
x = torch::torch_tensor(values, device = "cpu")
352358
)

R/sits_mixture_model.R

+3
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,9 @@ sits_mixture_model.raster_cube <- function(data, endmembers, ...,
201201
image_size = .tile_size(.tile(data)), memsize = memsize,
202202
multicores = multicores
203203
)
204+
# Terra requires at least two pixels to recognize an extent as valid
205+
# polygon and not a line or point
206+
block <- .block_regulate_size(block)
204207
# Prepare parallelization
205208
.parallel_start(workers = multicores, output_dir = output_dir)
206209
on.exit(.parallel_stop(), add = TRUE)

R/sits_mlp.R

+19-15
Original file line numberDiff line numberDiff line change
@@ -281,25 +281,29 @@ sits_mlp <- function(samples = NULL,
281281
values <- .pred_normalize(pred = values, stats = ml_stats)
282282
# Transform input into matrix
283283
values <- as.matrix(values)
284-
# Do classification
285-
values <- stats::predict(object = torch_model, values)
284+
# if CUDA is available, transform to torch data set
285+
# Load into GPU
286+
if (torch::cuda_is_available()) {
287+
values <- .as_dataset(values)
288+
# We need to transform in a dataloader to use the batch size
289+
values <- torch::dataloader(
290+
values, batch_size = 2^15
291+
)
292+
# Do GPU classification
293+
values <- .try(
294+
stats::predict(object = torch_model, values),
295+
.msg_error = paste("An error occured while transfering",
296+
"data to GPU. Please reduce the value of",
297+
"the `gpu_memory` parameter.")
298+
)
299+
} else {
300+
# Do CPU classification
301+
values <- stats::predict(object = torch_model, values)
302+
}
286303
# Convert to tensor cpu to support GPU processing
287304
values <- torch::as_array(
288305
x = torch::torch_tensor(values, device = "cpu")
289306
)
290-
# Transform to a torch dataset
291-
values <- .as_dataset(values)
292-
# We need to transform in a dataloader to use the batch size
293-
values <- torch::dataloader(
294-
values, batch_size = 2^15
295-
)
296-
# Do classification
297-
values <- .try(
298-
stats::predict(object = torch_model, values),
299-
.msg_error = paste("An error occured while transfering",
300-
"data to GPU. Please reduce the value of",
301-
"the `gpu_memory` parameter.")
302-
)
303307
# Are the results consistent with the data input?
304308
.check_processed_values(
305309
values = values, input_pixels = input_pixels

R/sits_reduce.R

+3
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,9 @@ sits_reduce.raster_cube <- function(data, ...,
188188
image_size = .tile_size(.tile(data)), memsize = memsize,
189189
multicores = multicores
190190
)
191+
# Terra requires at least two pixels to recognize an extent as valid
192+
# polygon and not a line or point
193+
block <- .block_regulate_size(block)
191194
# Prepare parallelization
192195
.parallel_start(workers = multicores)
193196
on.exit(.parallel_stop(), add = TRUE)

0 commit comments

Comments
 (0)