Skip to content

Commit e2772cb

Browse files
Merge pull request #1074 from OldLipe/feat/appy_prop
Fix legend `sits_reclassify()` bug
2 parents 5188386 + 1e8fce6 commit e2772cb

13 files changed

+175
-61
lines changed

R/api_apply.R

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,8 @@
149149
base_tile = feature,
150150
block_files = block_files,
151151
multicores = 1,
152-
update_bbox = FALSE
152+
update_bbox = FALSE,
153+
normalized = normalized
153154
)
154155
# Return a feature tile
155156
band_tile

R/api_conf.R

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -937,7 +937,7 @@ NULL
937937
.conf_eo_band <- function(source, collection, band) {
938938
# Format band name
939939
band <- .band_eo(band)
940-
# Return a default value if band does not exists in config
940+
# does the band exists in cube config?
941941
if (!.conf_eo_band_exists(source, collection, band)) {
942942
return(NULL)
943943
}

R/api_raster.R

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -652,6 +652,24 @@
652652
UseMethod(".raster_freq", pkg_class)
653653
}
654654

655+
#' @title Raster package internal raster data type
656+
#' @name .raster_datatype
657+
#' @keywords internal
658+
#' @noRd
659+
#' @author Felipe Carvalho, \email{felipe.carvalho@@inpe.br}
660+
#'
661+
#' @param r_obj raster package object
662+
#' @param by_layer A logical value indicating the type of return
663+
#' @param ... additional parameters to be passed to raster package
664+
#'
665+
#' @return A character value with data type
666+
.raster_datatype <- function(r_obj, ..., by_layer = TRUE) {
667+
# check package
668+
pkg_class <- .raster_check_package()
669+
670+
UseMethod(".raster_datatype", pkg_class)
671+
}
672+
655673
#' @title Raster package internal summary values function
656674
#' @name .raster_summary
657675
#' @keywords internal

R/api_raster_terra.R

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -459,6 +459,21 @@
459459
terra::freq(x = r_obj, bylayer = TRUE)
460460
}
461461

462+
#' @title Raster package internal raster data type
463+
#' @name .raster_datatype
464+
#' @keywords internal
465+
#' @noRd
466+
#' @author Felipe Carvalho, \email{felipe.carvalho@@inpe.br}
467+
#'
468+
#' @param r_obj raster package object
469+
#' @param by_layer A logical value indicating the type of return
470+
#' @param ... additional parameters to be passed to raster package
471+
#'
472+
#' @return A character value with data type
473+
.raster_datatype.terra <- function(r_obj, ..., by_layer = TRUE) {
474+
terra::datatype(x = r_obj, bylyr = by_layer)
475+
}
476+
462477
#' @title Summary values of terra object
463478
#' @keywords internal
464479
#' @noRd

R/api_reclassify.R

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,3 +194,19 @@
194194
# Return closure
195195
reclassify_fn
196196
}
197+
198+
.reclassify_new_labels <- function(cube, rules) {
199+
# Get cube labels
200+
cube_labels <- .cube_labels(cube, dissolve = FALSE)[[1]]
201+
# Get rules new labels
202+
new_labels <- setdiff(names(rules), cube_labels)
203+
# Does rules has new labels in the composition?
204+
if (.has(new_labels) > 0) {
205+
# Get the next index
206+
next_idx <- max(as.numeric(names(cube_labels))) + 1
207+
idx_values <- seq.int(
208+
from = next_idx, to = next_idx + length(new_labels) - 1 )
209+
names(new_labels) <- as.character(idx_values)
210+
}
211+
return(c(cube_labels, new_labels))
212+
}

R/api_space_time_operations.R

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@
129129
.contains <- function(x, y) {
130130
as_crs <- sf::st_crs(x)
131131
y <- sf::st_transform(y, crs = as_crs)
132-
apply(sf::st_contains(x, y, sparse = FALSE), 1, any)
132+
apply(suppressMessages(sf::st_contains(x, y, sparse = FALSE)), 1, any)
133133
}
134134
#' @title Find the closest points.
135135
#'

R/api_tile.R

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -526,11 +526,13 @@ NULL
526526
#' @name .tile_band_conf
527527
#' @keywords internal
528528
#' @noRd
529-
#' @param tile A tile.
530-
#' @param band Band character vector.
529+
#' @param tile A tile.
530+
#' @param band Band character vector.
531+
#' @param normalized A logical indicating if band is normalized.
532+
#' @param ... Additional parameters.
531533
#'
532534
#' @return band_conf or band_cloud_conf
533-
.tile_band_conf <- function(tile, band) {
535+
.tile_band_conf <- function(tile, band, ...) {
534536
UseMethod(".tile_band_conf", tile)
535537
}
536538
#' @export
@@ -552,13 +554,13 @@ NULL
552554
return(NULL)
553555
}
554556
#' @export
555-
.tile_band_conf.derived_cube <- function(tile, band) {
557+
.tile_band_conf.derived_cube <- function(tile, band, ...) {
556558
.conf_derived_band(
557559
derived_class = .tile_derived_class(tile), band = band[[1]]
558560
)
559561
}
560562
#' @export
561-
.tile_band_conf.default <- function(tile, band) {
563+
.tile_band_conf.default <- function(tile, band, ...) {
562564
tile <- tibble::as_tibble(tile)
563565
tile <- .cube_find_class(tile)
564566
band_conf <- .tile_band_conf(tile, band)

R/sits_apply.R

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,12 @@
5252
#' inside the kernel window. Central pixel is \code{NA} just only
5353
#' all pixels in the window are \code{NA}.
5454
#'
55+
#' By default, the indexes generated by the \code{sits_apply()} function are
56+
#' normalized between -1 and 1, scaled by a factor of 0.0001.
57+
#' Normalized indexes are saved as INT2S (Integer with sign).
58+
#' If the \code{normalized} parameter is FALSE, no scaling factor will be
59+
#' applied and the index will be saved as FLT4S (Float with sign).
60+
#'
5561
#' @section Summarizing kernel functions:
5662
#' \itemize{
5763
#' \item{\code{w_median()}: returns the median of the neighborhood's values.}
@@ -125,6 +131,8 @@ sits_apply.raster_cube <- function(data, ...,
125131
.check_is_regular(data)
126132
# Check window size
127133
.check_window_size(window_size)
134+
# Check normalized index
135+
.check_lgl(normalized)
128136
# Check memsize
129137
.check_memsize(memsize, min = 1, max = 16384)
130138
# Check multicores

R/sits_reclassify.R

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -182,8 +182,8 @@ sits_reclassify.class_cube <- function(cube,
182182
},
183183
.msg_error = "mask roi does not intersect cube"
184184
)
185-
# Get output labels
186-
labels <- unique(c(.cube_labels(cube), names(rules)))
185+
# Get new labels from cube and pre-defined rules from user
186+
labels <- .reclassify_new_labels(cube, rules)
187187
# Classify the data
188188
class_tile <- .reclassify_tile(
189189
tile = tile,

man/sits-package.Rd

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

man/sits_apply.Rd

Lines changed: 6 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tests/testthat/test-apply.R

Lines changed: 86 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
test_that("EVI generation", {
1+
test_that("Testing normalized index generation", {
22
s2_cube <- tryCatch(
33
{
44
sits_cube(
@@ -26,8 +26,8 @@ test_that("EVI generation", {
2626
suppressWarnings(dir.create(dir_images))
2727
}
2828
unlink(list.files(dir_images,
29-
pattern = "\\.tif$",
30-
full.names = TRUE
29+
pattern = "\\.tif$",
30+
full.names = TRUE
3131
))
3232

3333

@@ -43,12 +43,12 @@ test_that("EVI generation", {
4343
)
4444

4545
gc_cube_new <- sits_apply(gc_cube,
46-
EVI2 = 2.5 * (B8A - B05) / (B8A + 2.4 * B05 + 1),
47-
multicores = 1,
48-
output_dir = dir_images
46+
EVI = 2.5 * (B8A - B05) / (B8A + 2.4 * B05 + 1),
47+
multicores = 1,
48+
output_dir = dir_images
4949
)
5050

51-
expect_true(all(sits_bands(gc_cube_new) %in% c("EVI2", "B05", "B8A")))
51+
expect_true(all(sits_bands(gc_cube_new) %in% c("EVI", "B05", "B8A")))
5252

5353
timeline <- sits_timeline(gc_cube_new)
5454
start_date <- timeline[1]
@@ -63,7 +63,7 @@ test_that("EVI generation", {
6363
file_info_b8a <- .fi(gc_cube_new) |> .fi_filter_bands(bands = "B8A")
6464
b8a_band_1 <- .raster_open_rast(file_info_b8a$path[[1]])
6565

66-
file_info_evi2 <- .fi(gc_cube_new) |> .fi_filter_bands(bands = "EVI2")
66+
file_info_evi2 <- .fi(gc_cube_new) |> .fi_filter_bands(bands = "EVI")
6767
evi2_band_1 <- .raster_open_rast(file_info_evi2$path[[1]])
6868

6969
b05_100 <- as.numeric(b05_band_1[100] / 10000)
@@ -104,14 +104,87 @@ test_that("EVI generation", {
104104
progress = FALSE)
105105
evi_tibble_2 <- sits_apply(
106106
evi_tibble,
107-
EVI2_NEW = 2.5 * (B8A - B05) / (B8A + 2.4 * B05 + 1)
107+
EVI_NEW = 2.5 * (B8A - B05) / (B8A + 2.4 * B05 + 1)
108108
)
109109

110-
values_evi2 <- .tibble_time_series(evi_tibble_2)$EVI2
111-
values_evi2_new <- .tibble_time_series(evi_tibble_2)$EVI2_NEW
110+
values_evi2 <- .tibble_time_series(evi_tibble_2)$EVI
111+
values_evi2_new <- .tibble_time_series(evi_tibble_2)$EVI_NEW
112112
expect_equal(values_evi2, values_evi2_new, tolerance = 0.001)
113113
})
114114

115+
test_that("Testing non-normalized index generation", {
116+
data_dir <- system.file("extdata/raster/mod13q1", package = "sits")
117+
cube <- sits_cube(
118+
source = "BDC",
119+
collection = "MOD13Q1-6",
120+
data_dir = data_dir,
121+
progress = FALSE
122+
)
123+
124+
125+
dir_images <- paste0(tempdir(), "/images/")
126+
if (!dir.exists(dir_images)) {
127+
suppressWarnings(dir.create(dir_images))
128+
}
129+
gc_cube_new <- sits_apply(cube,
130+
XYZ = 1 / NDVI * 0.25,
131+
normalized = FALSE,
132+
multicores = 2,
133+
output_dir = dir_images
134+
)
135+
136+
expect_true(all(sits_bands(gc_cube_new) %in% c("NDVI", "XYZ")))
137+
138+
file_info_ndvi <- .fi(gc_cube_new) |> .fi_filter_bands(bands = "NDVI")
139+
ndvi_band_1 <- .raster_open_rast(file_info_ndvi$path[[1]])
140+
141+
file_info_xyz <- .fi(gc_cube_new) |> .fi_filter_bands(bands = "XYZ")
142+
xyz_band_1 <- .raster_open_rast(file_info_xyz$path[[1]])
143+
144+
scale_factor <- 10000
145+
ndvi_100 <- as.numeric(ndvi_band_1[100] / 10000)
146+
xyz_100 <- as.numeric(xyz_band_1[100] / 10000) * scale_factor
147+
148+
xyz_calc_100 <- 1 / ndvi_100 * 0.25
149+
expect_equal(xyz_100, xyz_calc_100, tolerance = 0.001)
150+
151+
ndvi_150 <- as.numeric(ndvi_band_1[150] / 10000)
152+
xyz_150 <- as.numeric(xyz_band_1[150] / 10000) * scale_factor
153+
154+
xyz_calc_150 <- 1 / ndvi_150 * 0.25
155+
expect_equal(xyz_150, xyz_calc_150, tolerance = 0.001)
156+
157+
bbox_cube <- sits_bbox(gc_cube_new, as_crs = "EPSG:4326")
158+
lats <- runif(10, min = bbox_cube[["ymin"]], max = bbox_cube[["ymax"]])
159+
longs <- runif(10, min = bbox_cube[["xmin"]], max = bbox_cube[["xmax"]])
160+
161+
timeline <- sits_timeline(gc_cube_new)
162+
start_date <- timeline[1]
163+
end_date <- timeline[length(timeline)]
164+
165+
csv_tb <- purrr::map2_dfr(lats, longs, function(lat, long) {
166+
tibble::tibble(
167+
longitude = long,
168+
latitude = lat,
169+
start_date = start_date,
170+
end_date = end_date,
171+
label = "NoClass"
172+
)
173+
})
174+
csv_file <- paste0(tempdir(), "/csv_gc_cube2.csv")
175+
write.csv(csv_tb, file = csv_file)
176+
177+
xyz_tibble <- sits_get_data(gc_cube_new, csv_file, progress = FALSE)
178+
xyz_tibble_2 <- sits_apply(
179+
xyz_tibble,
180+
XYZ_NEW = 1 / NDVI * 0.25
181+
)
182+
183+
values_xyz2 <- .tibble_time_series(xyz_tibble)$XYZ
184+
values_xyz_new <- .tibble_time_series(xyz_tibble_2)$XYZ_NEW
185+
expect_equal(values_xyz2, values_xyz_new, tolerance = 0.001)
186+
})
187+
115188
test_that("Kernel functions", {
116189
data_dir <- system.file("extdata/raster/mod13q1", package = "sits")
117190
cube <- sits_cube(
@@ -225,8 +298,8 @@ test_that("Kernel functions", {
225298
expect_true(max_1 == max_2)
226299

227300
tif_files <- grep("tif",
228-
list.files(tempdir(), full.names = TRUE),
229-
value = TRUE
301+
list.files(tempdir(), full.names = TRUE),
302+
value = TRUE
230303
)
231304

232305
success <- file.remove(tif_files)

0 commit comments

Comments
 (0)