Skip to content

Commit

Permalink
Prepare CRAN release
Browse files Browse the repository at this point in the history
  • Loading branch information
vwmaus committed Mar 2, 2020
1 parent e1344a2 commit 98ba685
Show file tree
Hide file tree
Showing 14 changed files with 187 additions and 117 deletions.
23 changes: 10 additions & 13 deletions DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,17 +1,15 @@
Package: dtwSat
Type: Package
Title: Time-Weighted Dynamic Time Warping for Satellite Image Time Series Analysis
Version: 0.2.6.9999
Date: 2019-10-20
Version: 0.2.6
Date: 2020-03-02
Authors@R: c(person('Victor', 'Maus', role = c('aut', 'cre'), email = '[email protected]', comment = c(ORCID = "0000-0002-7385-4723")),
person('Marius', 'Appel', role = c('ctb')),
person('Nikolas', 'Kuschnig', role = c('ctb')),
person('Marius', 'Appel', role = c('ctb'), comment = c(ORCID = "0000-0001-5281-3896")),
person('Nikolas', 'Kuschnig', role = c('ctb'), comment = c(ORCID = "0000-0002-6642-2543")),
person('Toni', 'Giorgino', role = c('ctb')))
Description: Provides an implementation of the Time-Weighted Dynamic Time
Warping (TWDTW) method for land cover mapping using satellite image time series.
TWDTW is based on the Dynamic Time Warping technique and has achieved high
accuracy for land cover classification using satellite data. The method is
based on comparing unclassified satellite image time series with a set of known
TWDTW compares unclassified satellite image time series with a set of known
temporal patterns (e.g. phenological cycles associated with the vegetation).
Using 'dtwSat' the user can build temporal patterns for land cover types, apply
the TWDTW analysis for satellite datasets, visualize the results of the time
Expand Down Expand Up @@ -42,18 +40,17 @@ Imports:
Rdpack,
data.table
Suggests:
knitr,
rmarkdown,
gridExtra,
grid,
png,
Hmisc
License: GPL (>= 2) | file LICENSE
Hmisc,
rbenchmark
License: GPL (>= 3) | file LICENSE
URL: https://github.com/vwmaus/dtwSat/
BugReports: https://github.com/vwmaus/dtwSat/issues
Author: Victor Maus [aut, cre] (<https://orcid.org/0000-0002-7385-4723>),
Marius Appel [ctb],
Nikolas Kuschnig [ctb],
Marius Appel [ctb] (<https://orcid.org/0000-0001-5281-3896>),
Nikolas Kuschnig [ctb] (<https://orcid.org/0000-0002-6642-2543>),
Toni Giorgino [ctb]
Maintainer: Victor Maus <[email protected]>
LazyData: true
Expand Down
2 changes: 1 addition & 1 deletion NAMESPACE
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
# Generated by roxygen2: do not edit by hand

export(.twdtw_reduce_time)
export(asymmetric)
export(createPatterns)
export(getDatesFromDOY)
Expand Down Expand Up @@ -29,6 +28,7 @@ export(symmetric2)
export(twdtwApply)
export(twdtwApplyParallel)
export(twdtwClassify)
export(twdtw_reduce_time)
exportMethods("[")
exportMethods("[[")
exportMethods(as.data.frame)
Expand Down
6 changes: 5 additions & 1 deletion NEWS.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
# dtwSat v0.2.6.9999
# dtwSat v0.2.6

* Fixes error in to - from : non-numeric argument to binary operator in "twdtwAssess"

* Fixes bug in .twdtw fundtion

* Adds funtion for fast time series classification "twdtw_reduce_time" (~3x faster than twdtwApply)

# dtwSat v0.2.5

* Adds dtwSat paper published on Journal of Statistical Software
Expand Down
1 change: 0 additions & 1 deletion R/class-twdtwMatches.R
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@
#' @param patterns a \code{\link[dtwSat]{twdtwTimeSeries}} object.
#' @param alignments an object of class list with the TWDTW results with
#' the same length as \code{timeseries} or a list of twdtwMatches.
#' @param ... objects of class twdtwMatches.
#'
#' @include class-twdtwTimeSeries.R
#'
Expand Down
2 changes: 1 addition & 1 deletion R/twdtw.R
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
###############################################################

.twdtw = function(x, y, weight.fun, dist.method, step.matrix,
n, span, min.length, theta, keep){
n, span, min.length, keep){
labels = as.character(labels(y))
names(labels) = labels
timeseries = x[[1]]
Expand Down
23 changes: 9 additions & 14 deletions R/twdtwApply.R
Original file line number Diff line number Diff line change
Expand Up @@ -55,11 +55,6 @@
#' @param n An integer. The maximun number of matches to perform.
#' NULL will return all matches.
#'
#' @param theta Numeric between 0 and 1. The weight of the time
#' for the TWDTW computation. Use \code{theta=0} to cancel the time-weight,
#' \emph{i.e.} to run the original DTW algorithm. Default is 0.5, meaning that
#' the time has the same weight as the curve shape in the TWDTW analysis.
#'
#' @param keep Preserves the cost matrix, inputs, and other internal structures.
#' Default is FALSE. For plot methods use \code{keep=TRUE}.
#'
Expand Down Expand Up @@ -100,7 +95,7 @@
setGeneric(name = "twdtwApply",
def = function(x, y, resample=TRUE, length=NULL, weight.fun=NULL,
dist.method="Euclidean", step.matrix = symmetric1, n=NULL,
span=NULL, min.length=0, theta = 0.5, ...) standardGeneric("twdtwApply"))
span=NULL, min.length=0, ...) standardGeneric("twdtwApply"))


#' @rdname twdtwApply
Expand All @@ -121,7 +116,7 @@ setGeneric(name = "twdtwApply",
#' }
#' @export
setMethod(f = "twdtwApply", "twdtwTimeSeries",
def = function(x, y, resample, length, weight.fun, dist.method, step.matrix, n, span, min.length, theta, keep=FALSE, ...){
def = function(x, y, resample, length, weight.fun, dist.method, step.matrix, n, span, min.length, keep=FALSE, ...){
if(!is(y, "twdtwTimeSeries"))
stop("y is not of class twdtwTimeSeries")
if(!is(step.matrix, "stepPattern"))
Expand All @@ -132,11 +127,11 @@ setMethod(f = "twdtwApply", "twdtwTimeSeries",
stop("weight.fun is not a function")
if(resample)
y = resampleTimeSeries(object=y, length=length)
twdtwApply.twdtwTimeSeries(x, y, weight.fun, dist.method, step.matrix, n, span, min.length, theta, keep)
twdtwApply.twdtwTimeSeries(x, y, weight.fun, dist.method, step.matrix, n, span, min.length, keep)
})

twdtwApply.twdtwTimeSeries = function(x, y, weight.fun, dist.method, step.matrix, n, span, min.length, theta, keep){
res = lapply(as.list(x), FUN = .twdtw, y, weight.fun, dist.method, step.matrix, n, span, min.length, theta, keep)
twdtwApply.twdtwTimeSeries = function(x, y, weight.fun, dist.method, step.matrix, n, span, min.length, keep){
res = lapply(as.list(x), FUN = .twdtw, y, weight.fun, dist.method, step.matrix, n, span, min.length, keep)
new("twdtwMatches", timeseries=x, patterns=y, alignments=res)
}

Expand All @@ -147,7 +142,7 @@ twdtwApply.twdtwTimeSeries = function(x, y, weight.fun, dist.method, step.matrix
#' @example examples/test_twdtw_raster_analysis.R
#' @export
setMethod(f = "twdtwApply", "twdtwRaster",
def = function(x, y, resample, length, weight.fun, dist.method, step.matrix, n, span, min.length, theta,
def = function(x, y, resample, length, weight.fun, dist.method, step.matrix, n, span, min.length,
breaks=NULL, from=NULL, to=NULL, by=NULL, overlap=0.5, filepath="", ...){
if(!is(step.matrix, "stepPattern"))
stop("step.matrix is not of class stepPattern")
Expand Down Expand Up @@ -176,12 +171,12 @@ setMethod(f = "twdtwApply", "twdtwRaster",
breaks = as.Date(breaks)
if(resample)
y = resampleTimeSeries(object=y, length=length)
twdtwApply.twdtwRaster(x, y, weight.fun, dist.method, step.matrix, n, span, min.length, theta,
twdtwApply.twdtwRaster(x, y, weight.fun, dist.method, step.matrix, n, span, min.length,
breaks, overlap, filepath, ...)
})


twdtwApply.twdtwRaster = function(x, y, weight.fun, dist.method, step.matrix, n, span, min.length, theta,
twdtwApply.twdtwRaster = function(x, y, weight.fun, dist.method, step.matrix, n, span, min.length,
breaks, overlap, filepath, ...){


Expand Down Expand Up @@ -251,7 +246,7 @@ twdtwApply.twdtwRaster = function(x, y, weight.fun, dist.method, step.matrix, n,
# Apply TWDTW analysis
twdtw_results <- dtwSat::twdtwApply(x = ts, y = y, weight.fun = weight.fun, dist.method = dist.method,
step.matrix = step.matrix, n = n, span = span,
min.length = min.length, theta = theta, keep = FALSE)
min.length = min.length, keep = FALSE)

# Get best matches for each point, period, and pattern
m <- length(levels)
Expand Down
12 changes: 6 additions & 6 deletions R/twdtwApplyParallel.R
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
setGeneric(name = "twdtwApplyParallel",
def = function(x, y, resample = TRUE, length = NULL, weight.fun = NULL,
dist.method = "Euclidean", step.matrix = symmetric1, n = NULL,
span = NULL, min.length = 0, theta = 0.5, ...) standardGeneric("twdtwApplyParallel"))
span = NULL, min.length = 0, ...) standardGeneric("twdtwApplyParallel"))



Expand All @@ -40,7 +40,7 @@ setGeneric(name = "twdtwApplyParallel",
#' @example examples/test_twdtw_raster_analysis.R
#' @export
setMethod(f = "twdtwApplyParallel", "twdtwRaster",
def = function(x, y, resample, length, weight.fun, dist.method, step.matrix, n, span, min.length, theta,
def = function(x, y, resample, length, weight.fun, dist.method, step.matrix, n, span, min.length,
breaks=NULL, from=NULL, to=NULL, by=NULL, overlap=0.5, filepath="", ...){
if(!is(step.matrix, "stepPattern"))
stop("step.matrix is not of class stepPattern")
Expand Down Expand Up @@ -69,12 +69,12 @@ setMethod(f = "twdtwApplyParallel", "twdtwRaster",
breaks = as.Date(breaks)
if(resample)
y = resampleTimeSeries(object=y, length=length)
twdtwApplyParallel.twdtwRaster(x, y, weight.fun, dist.method, step.matrix, n, span, min.length, theta,
twdtwApplyParallel.twdtwRaster(x, y, weight.fun, dist.method, step.matrix, n, span, min.length,
breaks, overlap, filepath, ...)
})


twdtwApplyParallel.twdtwRaster = function(x, y, weight.fun, dist.method, step.matrix, n, span, min.length, theta,
twdtwApplyParallel.twdtwRaster = function(x, y, weight.fun, dist.method, step.matrix, n, span, min.length,
breaks, overlap, filepath, ...){

# Match raster bands to pattern bands
Expand Down Expand Up @@ -128,7 +128,7 @@ twdtwApplyParallel.twdtwRaster = function(x, y, weight.fun, dist.method, step.ma
pb <- pbCreate(bs$n, ...)

clusterExport(cl = cl, list = c("y", "weight.fun", "dist.method", "step.matrix", "n", "span",
"min.length", "theta", "breaks", "overlap"), envir = environment())
"min.length", "breaks", "overlap"), envir = environment())

fun <- function(k){

Expand All @@ -152,7 +152,7 @@ twdtwApplyParallel.twdtwRaster = function(x, y, weight.fun, dist.method, step.ma
# Apply TWDTW analysis
twdtw_results <- dtwSat::twdtwApply(x = ts, y = y, weight.fun = weight.fun, dist.method = dist.method,
step.matrix = step.matrix, n = n, span = span,
min.length = min.length, theta = theta, keep = FALSE)
min.length = min.length, keep = FALSE)

# Get best matches for each point, period, and pattern
levels <- dtwSat::levels(y)
Expand Down
83 changes: 56 additions & 27 deletions R/twdtw_reduce_time.R
Original file line number Diff line number Diff line change
@@ -1,42 +1,71 @@
#' @rdname twdtwApply
#' @aliases twdtwApply-twdtwTimeSeries
#' @include methods.R
#' @title Fast TWDTW apply
#' @name twdtw_reduce_time
#' @author Victor Maus, \email{vwmaus1@@gmail.com}
#' @rdname twdtw_reduce_time
#'
#' @examples
#' @description This function is a faster version of \link[dtwSat]{twdtwApply} (usually 3x faster).
#' It does not keep any intermediate data. It performs a multidimensional TWDTW analysis
#' \insertCite{Maus:2019}{dtwSat} and retrieves only the best matches between the unclassified
#' time series and the patterns for each defined time interval.
#'
#' @inheritParams twdtwApply
#' @inheritParams twdtwClassify
#'
#' # Read time series to be labelled from csv
#' ts_file <- system.file("reduce_time/ts_MODIS13Q1.csv", package = "dtwSat")
#' ts <- read.csv(ts_file, stringsAsFactors = FALSE)
#' @param x a data.frame with the target time series. Usually, it is an unclassified time series.
#' It must contain two or more columns, one column called \code{date} with dates in the format
#' "YYYY-MM-DD". The other columns can have any names (e.g., red, blue, nir, evi, ndvi) as long
#' as they match the column names in the temporal patterns \code{y}.
#'
#' # Read labelled temporal patterns from csv
#' pattern_files <- dir(system.file("reduce_time/patterns", package = "dtwSat"), full.names = TRUE)
#' patterns <- lapply(pattern_files, read.csv, stringsAsFactors = FALSE)
#' @param y a list of data.frama objects similar to \code{x}.
#' The temporal patterns used to classify the time series in \code{x}.
#'
#' # Label time series
#' ts_class <- .twdtw_reduce_time(x = ts, y = patterns, weight.fun = logisticWeight(-0.1, 50),
#' from = "2009-09-01", to = "2017-09-01", by = "6 month")
#' ts_class
#' @param fill An integer to fill the classification gaps.
#'
#' @examples
#' \dontrun{
#'
#' ts_class$pattern_name <- basename(pattern_files)[ts_class$label]
#' ts_class
#' library(dtwSat)
#' log_fun = logisticWeight(-0.1, 50)
#' from = "2009-09-01"
#' to = "2017-09-01"
#' by = "12 month"
#'
#' # S4 objects for original implementation
#' tw_patt = readRDS(system.file("lucc_MT/patterns/patt.rds", package = "dtwSat"))
#' tw_ts = twdtwTimeSeries(MOD13Q1.ts)
#'
#' # Table from csv for minimalist version
#' mn_patt <- lapply(dir(system.file("lucc_MT/patterns", package = "dtwSat"),
#' pattern = ".csv$", full.names = TRUE), read.csv, stringsAsFactors = FALSE)
#' mn_ts <- read.csv(system.file("reduce_time/ts_MODIS13Q1.csv", package = "dtwSat"),
#' stringsAsFactors = FALSE)
#'
#' # Benchtmark
#' rbenchmark::benchmark(
#' original = twdtwClassify(twdtwApply(x = tw_ts, y = tw_patt, weight.fun = log_fun),
#' from = from, to = to, by = by)[[1]],
#' minimalist = twdtw_reduce_time(x = mn_ts, y = mn_patt, weight.fun = log_fun,
#' from = from, to = to, by = by)
#' )
#' }
#'
#' @export
.twdtw_reduce_time = function(x,
y,
weight.fun = NULL,
dist.method = "Euclidean",
step.matrix = symmetric1,
from = NULL,
to = NULL,
by = NULL,
overlap = .5,
fill = 255){
twdtw_reduce_time = function(x,
y,
weight.fun = NULL,
dist.method = "Euclidean",
step.matrix = symmetric1,
from = NULL,
to = NULL,
by = NULL,
overlap = .5,
fill = 255){

# Split time series from dates
px <- x[,names(x)!="date",drop=FALSE]
tx <- as.Date(x$date)

## Basic use case

# Comput TWDTW alignments for all patterns
aligs <- lapply(seq_along(y), function(l){

Expand Down
17 changes: 10 additions & 7 deletions cran-comments.md
Original file line number Diff line number Diff line change
@@ -1,24 +1,27 @@
## Test environments
* Ubuntu 18.04 (64-bit), R 3.5.2
devtools::check(args = '--as-cran')
devtools::check(args = '--use-valgrind')
devtools::submit_cran()

* win-builder
devtools::check_win_release()
devtools::check_win_devel()
devtools::check_win_oldrelease()

* R-hub
rhub::check_for_cran(check_args = '--as-cran')


* Ubuntu 18.04 (64-bit), R 3.6.1
devtools::check(args = '--as-cran')
devtools::check(args = '--use-valgrind')
devtools::submit_cran()

## REVIEWS

# v0.2.6

* Fixes warnings from https://cran.r-project.org/web/checks/check_results_dtwSat.html

# v0.2.5

* The DOI in the CITATION is for a new JSS publication that will be registered after publication on CRAN.


# v0.2.4

# v0.2.3
Expand Down
2 changes: 1 addition & 1 deletion examples/benchmark_minimalist.R
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,6 @@ mn_ts <- read.csv(system.file("reduce_time/ts_MODIS13Q1.csv", package = "dtwSat"
# Benchtmark
rbenchmark::benchmark(
original = twdtwClassify(twdtwApply(x = tw_ts, y = tw_patt, weight.fun = log_fun), from = from, to = to, by = by)[[1]],
minimalist = .twdtw_reduce_time(x = mn_ts, y = mn_patt, weight.fun = log_fun, from = from, to = to, by = by)
minimalist = twdtw_reduce_time(x = mn_ts, y = mn_patt, weight.fun = log_fun, from = from, to = to, by = by)
)

Loading

0 comments on commit 98ba685

Please sign in to comment.