library(terra)
library(tidyverse)
library(sp)
library(phenofit) # install.packages("phenofit")
# remotes::install_github("rpkgs/sf2")
# remotes::install_github("kongdd/Ipaper")
# install.packages("data.table")
# install.packages("magrittr")
file_vi <- ".\\Data\\sentinel2_LYL_2_2019-2021_EVI2.tif"
file_qc <- ".\\Data\\sentinel2_LYL_2_2019-2021_SCL.tif"
read_rast <- function(file, dates = NULL) {
r = rast(file)
# guess date from band names
# Note that might be failed to guess date
if (is.null(dates)) {
dates = names(r) %>%
gsub("_", "", .) %>%
substr(1, 8) %>%
as.Date("%Y%m%d")
}
# 如果日期不存在,根据名称猜测日期
# 将日期变量和名称都改为日期
terra::time(r) = dates
names(r) = dates
r
}
rast2mat <- function(r, backval = 0.1) {
d_coord = sf2::rast_df(r[[1]])
arr = sf2::rast_array(r)
mat = Ipaper::array_3dTo2d(arr)
range = ext(r) %>% as.vector() # [xmin, xmax, ymin, ymax]
cellsize = res(r)
grid <- sf2::make_grid(range, cellsize)
x_mean = mat %>% rowMeans(na.rm = TRUE)
I_grid = which(!(x_mean <= backval | is.na(x_mean)))
d_coord = grid@coords %>% data.table::as.data.table() %>% magrittr::set_colnames(c("lon", "lat")) %>% cbind(I = 1:nrow(.), .)
Ipaper::listk(mat, dates = terra::time(r), x_mean,
d_coord, I_grid, grid, r = r)
}
l = read_rast(file_vi) %>% rast2mat()
l_qc <- read_rast(file_qc) %>% rast2mat()
dates = l$dates
data <- Ipaper::listk(VI = l$mat, QC = l_qc$mat, dates, qcFUN = qc_sentinel2)
# install.packages("Cairo")
library(Cairo)
# 1为运行,0为跳过
if (0) {
# explore raw file
b = read_rast(file_vi)
r = b[[6]]
# file_raw = "sentinel2_kongying_raw.pdf"
file_raw = "sentinel2_LYL_raw.pdf"
Ipaper::write_fig({
i = 1; terra::plot(b[[seq((i-1)*16+1, i*16)]])
i = 2; terra::plot(b[[seq((i-1)*16+1, i*16)]])
i = 3; terra::plot(b[[seq((i-1)*16+1, i*16)]])
i = 4; terra::plot(b[[seq((i-1)*16+1, i*16)]])
i = 5; terra::plot(b[[seq((i-1)*16+1, nlyr(b))]])
}, file_raw, 10, 8, use.cairo_pdf = FALSE)
# pdf_view(file_raw)
}
# 默认参数
opt_old <- get_options()
# 新设置的参数(问题:参数如何确定?)
opt <- list(
nptperyear = 20,
wFUN = wTSM, wmin = 0.2,
verbose = FALSE,
season = list(
# rFUN = "smooth_wWHIT", smooth_wHANTS, smooth_wSG, lambda = 0.5,
rFUN = "smooth_wHANTS", nf = 6, lambda = 10,
maxExtendMonth = 12, r_min = 0.0, r_max = 0.1),
# fine fitting parameters
fitting = list(nextend = 1, minExtendMonth = 0, maxExtendMonth = 0.5,
methods = c("AG", "Zhang", "Beck", "Elmore", "Gu")[3], #,"klos",, 'Gu'
iters = 1,
minPercValid = 0)
)
set.seed(1)
inds = sample(1:nrow(data$VI), 100) %>% sort()
inds = 1:nrow(data$VI)
# inds = c(858, 878, 1017, 1129, 1222, 1328, 3101) # bads, 878 is the last error
par(mfrow = c(4, 1), mar = c(0, 3, 1.6, 1), mgp = c(1.2, 0.6, 0))
set_options(options = opt, season = list(rtrough_max = 0.7))
library(phenofit)
library(Ipaper) # remotes::install_github("rpkgs/Ipaper")
library(sf2) # remotes::install_github("rpkgs/sf.extra")
library(rcolors)
# library(lattice.layers)
library(grid)
library(ggplot2)
library(ggnewscale)
library(lubridate)
library(zeallot)
library(stringr)
library(dplyr)
library(job)
library(sp)
# library(sf)
# library(terra)
library(data.table)
library(dplyr)
library(magrittr)
get_input <- function(i, data, wmin = 0.2, wmid = 0.5) {
d = data.table::data.table(VI = data$VI[i,], QC = data$QC[i, ])
if (!is.null(data$DOY)) {
# this is for MODIS DOY
d %<>% mutate(t = getRealDate(data$dates, data$DOY[i, ]))
}
library(zeallot)
c(d$QC_flag, d$w) %<-% data$qcFUN(d$QC, wmin = wmin, wmid = wmid)
d
}
Ipaper::InitCluster(32, kill = FALSE)
res = foreach(i = inds %>% set_names(.,.), icount()) %dopar% {
Ipaper::runningId(i, 1e2)
d = get_input(i, data)
# d$t = dates
library(phenofit)
input <- check_input(dates, d$VI, d$w, QC_flag = d$QC_flag,
nptperyear = get_options("nptperyear"),
maxgap = get_options("nptperyear") / 4, wmin = 0.2)
tryCatch({
# r = phenofit_point(d, dates)$pheno
brks <- season_mov(input, years.run = NULL)
rfit <- brks2rfit(brks) # used rough fitting directly
r <- get_pheno(rfit)$doy
}, error = function(e) {
message(sprintf('%s', e$message))
})
# plot_season(input, brks, title = i, show.legend = F)
}
# dev_off()
save(res, file = "sentinel2_LYL_V2.rda")
load("sentinel2_LYL_V2.rda")
df = res %>% rm_empty() %>% melt_list("gridId") %>% cbind(meth = "rough", .) #%>% dplyr::select(-meth)
df[, gridId := as.integer(gridId)]
# df[, meth := as.factor(meth)]
inds_bad = df[grep("_4", flag)]$gridId %>% unique() %>% sort()
select_first_nGS <- function(df, nGS = 1) {
ind_valid = rowMeans(df[, -(1:4)], na.rm = TRUE) %>% which.notna()
df = df[ind_valid, ] %>% cbind(I = 1:nrow(.), .) # rm all NA records
# inds_bad = df[, grep("_4", flag)]
gs = as.numeric(substr(df$flag, 6, 6))
inds_bad = gs %>% { which(. > nGS) }
if (length(inds_bad) == 0) {
return(df %>% select(-I, -TRS5.los))
}
info_bad = df[inds_bad, .N, .(gridId, meth, origin)] %>% select(-N)
df_bad = merge(df, info_bad) %>%
reorder_name(c("gridId", "meth", "origin", "flag"))
df_good = df[-df_bad$I, ]
df_mutiGS = dt_ddply(df_bad, .(gridId, meth, origin), function(d) {
los = d$TRS5.eos - d$TRS5.sos
n = length(los)
if (n > nGS) {
i_bad = which.min(los)
# if the smallest GS in the head or tail
if (i_bad %in% c(1, n)) {
d = d[-i_bad, ]
} else {
# rm the GS with the largest ratio of unintersect period with the current year
perc_bad_head = pmax(0 - d$TRS5.sos[1], 0) / d$TRS5.eos[1]
perc_bad_tail = pmax(d$TRS5.eos[n] - 365, 0) / d$TRS5.eos[n]
i_bad = ifelse(perc_bad_head >= perc_bad_tail, 1, n)
d = d[-i_bad, ]
}
n = nrow(d)
# if still > nGS, then only kept the l
if (n > nGS) {
ind = order(los, decreasing = TRUE)[1:nGS]
d = d[ind, ]
}
}
d %>% mutate(flag = sprintf("%s_%d", year(origin), 1:nrow(.)))
# d
})
rbind(
df_good %>% select(-I),
df_mutiGS %>% select(-I)
)
}
point2rast <- function(df, d_coord,
outdir = "OUTPUT", prefix = "phenofit", overwrite = TRUE)
{
mkdir(outdir)
sp2 <- as(df2sp(d_coord), "SpatialPixelsDataFrame")
# flags <- unique(df$flag) %>% sort()
d_grp = unique(df[, .(meth, flag)])[order(flag)]
for (i in 1:nrow(d_grp)) {
# if (i != 1) next()
METH = d_grp$meth[i]
FLAG = d_grp$flag[i]
outfile <- glue("{outdir}/{prefix}_{METH}_{FLAG}.tif")
mkdir(dirname(outfile))
if (file.exists(outfile) && !overwrite) next()
cat(outfile, "\n")
d <- df[flag == FLAG & meth == METH, ]
ind <- match(1:nrow(d_coord), d$gridId)
data <- d[ind, -(1:4)]
sp2@data <- data
r <- raster::brick(sp2) %>% rast() %>% set_names(names(sp2))
terra::writeRaster(r, outfile, overwrite = TRUE)
# rgdal::setCPLConfigOption("GDAL_PAM_ENABLED", "FALSE")
# file.remove(paste0(outfile, ".aux.xml")) # rm the .aux.xml file
}
}
prj84 = sp::CRS("+proj=longlat +datum=WGS84 +no_defs")
df2sp <- function (d, formula = ~lon + lat, prj) {
if (missing(prj))
prj <- prj84
coordinates(d) <- formula
proj4string(d) <- prj
return(d)
}
df2 = select_first_nGS(df, nGS = 1)
point2rast(df2, l$d_coord, outdir = "outdir",
prefix = "Sentinel2_LYL_Pheno", overwrite = TRUE)
files = dir("outdir", "*.tif", full.names = TRUE)
test <- rast(files)
plot(test[[12:22]])
plot(test[[23:33]])
plot(test[[34:44]])
plot(test[[45:55]])
plot(test[[56:66]])