Nothing
## vim:textwidth=128:expandtab:shiftwidth=4:softtabstop=4
##OLD use_sf_package <- TRUE
#' Subset an argoFloats Object
#'
#' Return a subset of an [`argoFloats-class`] object. This applies
#' only to objects of type `"index"`, as created with [getIndex()] or `subset()`
#' acting on such a value, or of type `"argos"`, as created with [readProfiles()].
#' (It cannot be used on objects of type `"profiles"`, as created with [getProfiles()].)
#' There are two ways to use `subset()`. **Method 1.** supply
#' the `subset` argument. This may be a logical vector indicating
#' which entries to keep (by analogy to the base-R `subset()`
#' function) or it may be an integer vector holding the indices of entries to
#' be retained. **Method 2.** do not supply `subset`. In this
#' case, the action is determined by the third (`...`)
#' argument; see \sQuote{Details}.
#'
#' The possibilities for the `...` argument are as follows.
#'
#' 1. An integer vector giving indices to keep.
#'
#' 2. A list named `circle` with numeric elements named `longitude`,
#' `latitude` and `radius`. The first two give the center of
#' the subset region, and the third gives the radius of
#' that region, in kilometers.
#'
#' 3. A list named `rectangle` that has elements named
#' `longitude` and `latitude`, two-element numeric vectors
#' giving the western and eastern, and southern and northern
#' limits of the selection region.
#'
#' 4. A list named `polygon` that has elements named `longitude` and `latitude`
#' that are numeric vectors specifying a polygon within which profiles
#' will be retained. The polygon must not be self-intersecting,
#' and an error message will be issued if it is. If the polygon is not closed
#' (i.e. if the first and last points do not coincide) the first point is pasted
#' onto the end, to close it.
#'
#' 5. A vector or list named `parameter` that holds character values that
#' specify the names of measured parameters to keep. See section 3.3 of
#' Reference 1 for a list of parameters.
#'
#' 6. A list named `time` that has elements `from` and `to` that are either
#' POSIXt times, or character strings that `subset()` will convert to
#' POSIXt times using [as.POSIXct()] with `tz="UTC"`.
#'
#' 7. A list named `institution` that holds a single character element that
#' names the institution. The permitted values are:
#' `"AO"` for Atlantic Oceanographic and Meteorological Laboratory;
#' `"BO"` for British Oceanographic Data Centre;
#' `"CS"` for Commonwealth Scientific and Industrial Research Organization;
#' `"HZ"` for China Second Institute of Oceanography;
#' `"IF"` for Ifremer, France;
#' `"IN"` for India National Centre for Ocean Information Services;
#' `"JA"` for Japan Meteorological Agency;
#' `"KM"` for Korea Meteorological Agency;
#' `"KO"` for Korea Ocean Research and Development Institute;
#' `"ME"` for Marine Environment Data Section; and
#' `"NM"` for National Marine Data & Information Service.
#'
#' 8. A list named `deep` that holds a logical value indicating whether argo floats
#' are deep argo (i.e. `profiler_type` 849, 862, and 864).
#'
#' 9. A list named `ID` that holds a character value specifying a float identifier.
#'
#' 10. A list named `ocean` that holds a single character element that names the
#' ocean. The permitted values are:
#' `"A"` for Atlantic Ocean Area, from 70 W to 20 E,
#' `"P"` for Pacific Ocean Area, from 145 E to 70 W, and
#' `"I"` for Indian Ocean Area, from 20 E to 145 E.
#'
#' 11. A character value named `dataMode`, equal to either `realtime` or `delayed`,
#' that selects whether to retain real-time data or delayed data. There are two
#' possibilities, depending on the `type` of the `x` argument.
#' **Case 1.** If `x` is of `type="index"`, then the subset is done by looking for the letters
#' `R` or `D` in the source filename. Note that a file in the
#' latter category may contain some profiles that are of delayed mode *and also*
#' some profiles that are of `realtime` or `adjusted` mode.
#' **Case 2.** If `x` is
#' of type `argos`, then the subset operation is done for each profile within
#' the dataset. Sometimes this will yield data arrays with zero columns.
#'
#' 12. An integer or character value named `cycle` that specifies which cycles are to be retained.
#' This is done by regular-expression matching of the filename, looking between the
#' underline character (`"_"`) and the suffix (`.nc`), but note that the expression
#' is made up of a compulsory component comprising 3 or 4 digits, and an optional
#' component that is either blank or the character `"D"` (which designates a
#' descending profile). Thus, `001` will match both `*_001.nc` and `*_001D.nc`.
#' Note this can be used for both `"index"` and `"argos"` types.
#'
#' 13. A character value named `direction`, equal to either "descent" or "ascent",
#' that selects whether to retain data from the ascent or decent phase.
#'
#' 14. An integer value named `profile` that selects which profiles
#' to retain. Note that this type of subset is possible only
#' for objects of type `"argos"`.
#'
#' 15. An integer value named `cycle` that selects which cycles
#' to retain.
#'
#' 16. A character value named `dataStateIndicator`, equal to either "0A", "1A",
#' "2B", "2B+", "2C", "2C+", "3B", or "3C" that selects which `dataStateIndicator`
#' to keep (see table 6 of Reference 1 for details of these codes).
#' This operation only works for objects of type `"argos"`.
#'
#' 17. A list named `section` that has four elements:
#' `longitude`,`latitude`, `width`, and `segments`. The first two of these
#' are numeric vectors that define the spine of the section, in degrees East
#' and North, respectively. These are both mandatory, while both `width` and `segments`
#' are optional. If given, `width` is taken as maximal distance between an Argo
#' and the spine, for that float to be retained. If `width` is not given, it
#' defaults to 100km. If given, `segments` is either `NULL` or a positive
#' integer. Setting `segments` to `NULL` will cause the float-spine distance
#' to be computed along a great-circle route. By contrast, if `segments` is an
#' integer, then the spine is traced using `stats::approx()`, creating
#' `segments` new points. If `segments` is not provided, it defaults to 100.
#'
#' In all cases, the notation is that longitude is positive
#' for degrees East and negative for degrees West, and that latitude
#' is positive for degrees North and negative for degrees South.
#' For more on this function, see Kelley et al. (2021).
#'
#' @param x an [`argoFloats-class`] object as created by [getIndex()].
#'
#' @param subset optional numerical or logical vector that indicates which
#' indices of `x@data$index` to keep (example 1).
#'
#' @param ... the first entry here must be either (a) a list named `circle`,
#' `rectangle`, `polygon`, `parameter`, `time`, `institution`,
#' `ID`,`ocean`,`dataMode`,`cycle`, `direction`, `profile`, or `section`.
#' (examples 2 through 8, and 10 through 17),
#' or (b) a logical value named `deep` (example 9). Optionally, this entry
#' may be followed by second entry named `silent`, which is a logical
#' value indicating whether to prevent the printing of messages that
#' indicate the number (and percentage) of data that are kept
#' during the subsetting operation.
#' See \dQuote{Details} and \dQuote{Examples}.
#'
#' @return An [`argoFloats-class`] object, restricted as indicated.
#'
#' @examples
#' library(argoFloats)
#' data(index)
#' data(indexSynthetic)
#'
#' # Subset to the first 3 profiles in the (built-in) index
#' indexFirst3 <- subset(index, 1:3)
#'
#' # Subset to a circle near Abaco Island
#' indexCircle <- subset(index, circle=list(longitude=-77.5, latitude=27.5, radius=50))
##
## # NOTE: this example was removed because it requires using tempdir, which
## # is not something we want to encourage, since it goes against the whole idea
## # of caching.
## # Example 2B: subset a 300 km radius around Panama using "maps" package
## # This example requires downloading.
## \donttest{
## library("maps")
## data(world.cities)
## ai <- getIndex()
## panama <- subset(world.cities, name=="Panama")
## index1 <- subset(ai, circle=list(longitude=panama$long, latitude=panama$lat, radius=200))
##}
#'
#' # Subset to a rectangle near Abaco Island
#' lonlim <- c(-76.5, -76)
#' latlim <- c(26.5, 27.5)
#' indexRectangle <- subset(index, rectangle=list(longitude=lonlim, latitude=latlim))
#'
#' # Subset to a polygon near Abaco Island
#' lonp <- c(-77.492, -78.219, -77.904, -77.213, -76.728, -77.492)
#' latp <- c( 26.244, 25.247, 24.749, 24.987, 25.421, 26.244)
#' indexPolygon <- subset(index, polygon=list(longitude=lonp, latitude=latp))
##
## # Show some of these subsets on a map
## plot(index, bathymetry=FALSE)
## points(index2[["longitude"]], index2[["latitude"]], col=2, pch=20, cex=1.4)
## points(index3[["longitude"]], index3[["latitude"]], col=3, pch=20, cex=1.4)
## rect(lonRect[1], latRect[1], lonRect[2], latRect[2], border=3, lwd=2)
## points(index4[["longitude"]], index4[["latitude"]], col=4, pch=20, cex=1.4)
## polygon(p$longitude, p$latitude, border=4)
#'
#' # Subset to year 2019
#' index2019 <- subset(index, time=list(from="2019-01-01", to="2019-12-31"))
#'
#' # Subset to Canadian MEDS data
#' indexMEDS <- subset(index, institution="ME")
##
## # NOTE: this example was removed because it requires using tempdir, which
## # is not something we want to encourage, since it goes against the whole idea
## # of caching.
## # Example 8: subset to a specific ID
## # This example requires downloading.
## \donttest{
## ai <- getIndex(filename="synthetic")
## index9 <- subset(ai, ID="1900722")
##}
##
## # NOTE: this example was removed because it requires using tempdir, which
## # is not something we want to encourage, since it goes against the whole idea
## # of caching.
## # Example 9: subset data to only include deep argo
## # This example requires downloading.
## \donttest{
## ai <- getIndex(filename="synthetic")
## index8 <- subset(ai, deep=TRUE)
##}
##
## # NOTE: this example was removed because it requires using tempdir, which
## # is not something we want to encourage, since it goes against the whole idea
## # of caching.
## # Example 10: subset data by ocean
## # This example requires downloading.
## \donttest{
## ai <- getIndex()
## index10 <- subset(ai, circle=list(longitude=-83, latitude=9, radius=500))
## plot(index10, which="map", bathymetry=FALSE)
## atlantic <- subset(index10, ocean="A") # Subsetting for Atlantic Ocean
## pacific <- subset(index10, ocean="P")
## points(atlantic[["longitude"]], atlantic[["latitude"]], pch=20, col=2)
## points(pacific[["longitude"]], pacific[["latitude"]], pch=20, col=3)
##}
##
## # NOTE: there is no example 11.
##
## # NOTE: this example was removed because it requires using tempdir, which
## # is not something we want to encourage, since it goes against the whole idea
## # of caching.
## # Example 11: subset by delayed time
## # This example requires downloading.
## \donttest{
## data(indexBgc)
## index11 <- subset(indexBgc, dataMode="delayed")
## profiles <- getProfiles(index11)
## argos <- readProfiles(profiles)
## oxygen <- argos[["oxygen"]][[3]]
## pressure <- argos[["pressure"]][[3]]
## plot(oxygen, pressure, ylim=rev(range(pressure, na.rm=TRUE)),
## ylab="Pressure (dbar)", xlab="Oxygen (umol/kg)")
##}
##
## # Example 12: subset by cycle
## data(index)
## index12A <- subset(index, cycle="124")
## index12B <- subset(index, cycle=0:2)
## cat("File names with cycle number 124:", paste(index12A[["file"]]), "\n")
## cat("File names with cycle number between 0 and 2:", paste(index12B[["file"]]), "\n")
##
##
## # NOTE: this example was removed because it requires using tempdir, which
## # is not something we want to encourage, since it goes against the whole idea
## # of caching.
## # Example 13: subset by direction
## # This example requires downloading.
## \donttest{
## library(argoFloats)
## index13A <- subset(getIndex(), deep=TRUE)
## index13B <- subset(index13A, direction="descent")
## head(index13B[["file"]])
##}
##
## # NOTE: this example was removed because it requires using tempdir, which
## # is not something we want to encourage, since it goes against the whole idea
## # of caching.
## # Example 14: subset by profile (for argos type)
## # This example requires downloading.
## \donttest{
## library(argoFloats)
## index14A <- subset(getIndex(filename="synthetic"), ID="5903889")
## index14B <- subset(index14A, cycle="074")
## argos14A <- readProfiles(getProfiles(index14B))
## argos14B <- subset(argos14A, profile=1)
## D <- data.frame(Oxygen = argos14A[["oxygen"]],
## col1= argos14B[["oxygen"]][[1]])
##}
##
## # NOTE: this example was removed because it requires using tempdir, which
## # is not something we want to encourage, since it goes against the whole idea
## # of caching.
## # Example 15: subset by cycle (for argos type) to create TS diagram
## # This example requires downloading.
## \donttest{
## data("index")
## index15 <- subset(index, ID="1901584")
## profiles <- getProfiles(index15)
## argos <- readProfiles(profiles)
## plot(subset(argos, cycle="147"), which="TS")
##}
##
## # NOTE: this example was removed because it requires using tempdir, which
## # is not something we want to encourage, since it goes against the whole idea
## # of caching.
## # Example 16: subset by dataStateIndicator
## # This example requires downloading.
## \donttest{
## data("index")
## index16 <- subset(index, 1:40)
## argos <- readProfiles(getProfiles(index16))
## argos16A <- subset(argos, dataStateIndicator="2C")
## argos16B <- subset(argos, dataStateIndicator="2B")
##}
##
## # Example 17: subset by section to create a map plot
## if (requireNamespace("s2")) {
## data("index")
## lon <- c(-78, -77, -76)
## lat <-c(27.5,27.5,26.5)
## index17 <- subset(index,
## section=list(longitude=lon, latitude=lat, width=50))
## plot(index17, bathymetry=FALSE)
## points(lon, lat, pch=21, col="black", bg="red", type="o", lwd=3)
##}
#'
#' # Subset to profiles with oxygen data
#' indexOxygen <- subset(indexSynthetic, parameter="DOXY")
#'
#' # Subset to profiles with both salinity and 380-nm downward irradiance data
#' indexSalinityIrradiance <- subset(indexSynthetic, parameter=c("PSAL", "DOWN_IRRADIANCE380"))
#'
#' @references
#' 1. Carval, Thierry, Bob Keeley, Yasushi Takatsuki, Takashi Yoshida, Stephen Loch,
#' Claudia Schmid, and Roger Goldsmith. Argo User's Manual V3.3. Ifremer, 2019.
#' `doi:10.13155/29825`.
#' 2. Kelley, D. E., Harbin, J., & Richards, C. (2021). argoFloats: An R package for analyzing
#' Argo data. Frontiers in Marine Science, (8), 636922.
#' \doi{10.3389/fmars.2021.635922}
#'
#' @importFrom stats approx
#'
#' @importFrom oce geodDist
#'
#' @export
#'
#' @author Dan Kelley and Jaimie Harbin
setMethod(f="subset",
signature="argoFloats",
definition=function(x, subset=NULL, ...)
{
if (x@metadata$type == "profiles")
stop("in subset,argoFloats-method() :\n subset doesn't work for type = profiles", call.=FALSE)
## subsetString <- paste(deparse(substitute(subset)), collapse=" ")
dots <- list(...)
dotsNames <- names(dots)
## Clear the "debug" and "silent" entries from dots, because later we insist that length(dots) be 1.
debug <- 0
if ("debug" %in% dotsNames) {
debug <- dots$debug
dots$debug <- NULL
dotsNames <- names(dots)
}
silent <- 0
if ("silent" %in% dotsNames) {
silent <- dots$silent
dots$silent <- NULL
dotsNames <- names(dots)
}
## All done with manipulating dots now.
argoFloatsDebug(debug, "subset,argoFloats-method() {\n", style="bold", sep="", unindent=1)
## message("type =", x@metadata$type)
## Step 1: handle "argo" type first. Note that "subset" is ignored; rather, we insist that either
## "profile" or "cycle" be provided.
if (x@metadata$type == "argos") {
N <- x[["length"]]
if (!missing(subset)) {
N <- x[["length"]]
if (is.logical(subset)) {
if (length(subset) != x[["length"]])
stop("in subset,argoFloats-method() :\n 'subset' length (", length(subset), ") must match x length (", x[["length"]], ")",
call.=FALSE)
keep <- which(subset)
} else if (is.numeric(subset)) {
if (!all(subset > 0))
stop("in subset,argoFloats-method() :\n 'subset' must consist only of positive integers",
call.=FALSE)
if (any(subset > x[["length"]]))
stop("in subset,argoFloats-method() :\n 'subset' must not contain indices beyond range of `x` (in this case, ", x[["length"]], ")",
call.=FALSE)
keep <- subset
} else {
stop("in subset,argoFloats-method() :\n 'subset' must either be a logical vector or a list of indices",
call.=FALSE)
}
res <- x
res@data$argos <- x@data$argos[keep]
if (!silent)
message("Kept ", length(keep), " cycles (", sprintf("%.3g", 100*length(keep)/N), "%)")
argoFloatsDebug(debug, "} # subset,argoFloats-method()\n", style="bold", sep="", unindent=1)
return(res)
}
argoFloatsDebug(debug, "subsetting with type=\"argos\"\n")
if (length(dotsNames) == 0)
stop("in subset,argoFloats-method() :\n must give \"profile\" , \"cycle\", or \"dataStateIndicator\" argument", call.=FALSE)
if (dotsNames[1] == "profile") {
argoFloatsDebug(debug, "subsetting by profile ", profile, "\n")
profile <- dots[[1]]
## Loop over all objects within the data, and within that loop look at data within the object,
## and for each of them, if its a vactor subset according to profile and if its a matrix
## subset according to profile
res <- x
argos <- x[["argos"]]
## Loop over all objects
##message("profile=",paste(profile, collapse=" "))
for (iargo in seq_along(argos)) {
argo <- argos[[iargo]]
## Handle the metadata slot
for (name in names(argo@metadata)) {
##message("name=",name)
argoFloatsDebug(debug, "subsetting metadata item named \"", name, "\"\n", sep="")
## Pass some things through directly.
if (name %in% c("units", "filename", "flagScheme", "dataNamesOriginal"))
next
item <- argo@metadata[[name]]
## Handle things that are encoded as characters in a string,
## namely "direction", "juldQC", and "positionQC".
if (name == "direction" || grepl("QC$", name)) {
## message(" -- character")
res@data$argos[[iargo]]@metadata[[name]] <- paste(strsplit(item,"")[[1]][profile],collapse="")
} else if (is.list(item)) {
##message("list")
for (l in seq_along(item)) {
##print(dim(item[[l]]))
D <- dim(item[[l]])
if (profile > D[2])
stop("in subset,argoFloats-method() :\n cannot access profile ", profile, " of metadata item \"", name, "\" because its dimension is ", paste(D, collapse=" "), call.=FALSE)
##cat("BEFORE:\n");print(dim(res@data$argos[[iargo]]@metadata[[name]][[l]]))
res@data$argos[[iargo]]@metadata[[name]][[l]] <- item[[l]][, profile, drop=FALSE]
##cat("AFTER:\n");print(dim(res@data$argos[[iargo]]@metadata[[name]][[l]]))
}
} else if (is.vector(name)) {
##message("vector")
res@data$argos[[iargo]]@metadata[[name]] <- item[profile]
} else if (is.matrix(name)) {
##message("matrix")
res@data$argos[[iargo]]@metadata[[name]] <- item[, profile, drop=FALSE]
} else if (is.array(name)) {
argoFloatsDebug(debug, "name=", name, " has dim ", paste(dim(res@metadata[[name]]), collapse=" "), "\n")
if (length(dim(res@metadata[[name]])) <= 3) {
res@metadata[[name]] <- item[, , keep, drop=FALSE]
} else {
warning("not subsetting \"", name, "\" in metadata, because it is an array of rank > 3")
}
} else {
stop("cannot subset metadata item named \"", name, "\" because it is not a length-one string, a vector, or a matrix")
}
}
## Handle the data slot
for (name in names(argo@data)) {
item <- argo@data[[name]]
if (is.matrix(item)) {
dim <- dim(item)
if (profile > dim[2])
stop("in subset,argoFloats-method() :\n Only have ", dim[2], " profiles", call.=FALSE)
newItem <- item[, profile, drop=FALSE]
res@data$argos[[iargo]]@data[[name]] <- newItem
} else {
length <- length(item)
if (profile > length)
stop("in subset,argoFloats-method() :\n Only have ", length, " profiles", call.=FALSE)
newItem <- item[profile, drop=FALSE]
res@data$argos[[iargo]]@data[[name]] <- newItem
}
}
}
argoFloatsDebug(debug, "} # subset,argoFloats-method()\n", style="bold", sep="", unindent=1)
res@processingLog <- oce::processingLogAppend(res@processingLog,
paste("subset argos type for profile=", profile))
return(res)
} else if (dotsNames[1] == "ID") {
istraj <- identical(x@metadata$subtype, "trajectories")
argoFloatsDebug(debug, "subsetting an argos object by ID\n")
ID <- as.character(dots[[1]]) # convert in case it is numeric
xID <- x[["ID"]]
keep <- rep(FALSE, length(xID))
for (thisID in ID)
keep <- keep | grepl(thisID, xID)
if (!silent && !istraj) {
message("Kept ", sum(keep), " cycles (", sprintf("%.3g", 100*sum(keep)/N), "%)")
} else if (!silent && istraj) {
message("Kept ", sum(keep), " trajectories (", sprintf("%.3g", 100*sum(keep)/N), "%)")
}
x@data$argos <- x@data$argos[keep]
x@processingLog <- oce::processingLogAppend(x@processingLog,
paste("subset argos type by float ID", ID))
} else if (dotsNames[1] == "cycle") {
argoFloatsDebug(debug, "subsetting by cycle for 'argos' type\n")
cycle <- dots[[1]]
if (!is.character(cycle) & !is.numeric(cycle))
stop("in subset,argoFloats-method() : \"cycle\" must be character value or numeric value", call.=FALSE)
## Calculate 'keep', a logical vector that will be used for the actual subsetting.
xcycle <- x[["cycle"]]
argoFloatsDebug(debug, "x[[\"cycle\"]]: ", paste(xcycle, collapse=" "), "\n")
argoFloatsDebug(debug, "cycle: ", cycle, "\n")
if (is.character(cycle)) {
argoFloatsDebug(debug, "subsetting by cycle as a character value\n")
## Here, keep is logical
keep <- rep(FALSE, length(xcycle))
for (thisCycle in cycle)
keep <- keep | grepl(thisCycle, xcycle)
nkeep <- sum(keep)
} else if (is.numeric(cycle)) {
argoFloatsDebug(debug, "subsetting by cycle as a numeric value\n")
## Here, keep is integer
keep <- NULL
xcycle <- as.integer(gsub("AD","",xcycle)) # change e.g. "123D" to "123"
for (thisCycle in cycle) {
keep <- c(keep, which(thisCycle == xcycle))
## message("thisCycle=", thisCycle, " keep=", paste(keep, collapse=" "))
}
nkeep <- length(keep)
}
if (nkeep < 1)
warning("In subset,argoFloats-method(..., parameter) : found no profiles with given cycle(s)", call.=FALSE)
if (!silent)
message("Kept ", nkeep, " cycles ")
x@data[[1]] <- x@data[[1]][keep]
x@processingLog <- oce::processingLogAppend(x@processingLog,
paste("subset argos type for cycle=", cycle))
} else if (dotsNames[1] == "dataStateIndicator") {
argoFloatsDebug(debug, "subsetting by dataStateIndicator\n")
dataStateIndicator <- dots[[1]]
if (is.list(dots[1]))
dataStateIndicator <- unlist(dataStateIndicator)
## Reference Table 6, in section 3.6, of
## Argo Data Management Team. “Argo User's Manual V3.3.”
## Ifremer, November 28, 2019. https://doi.org/10.13155/29825.
if (!is.character(dataStateIndicator))
stop("in subset,argoFloats-method() : \"dataStateIndicator\" must be character value", call.=FALSE)
## In next, [1] means we take the first element (first profile) of the cycle.
dsi <- sapply(x[["argos"]], function(a) a[["dataStateIndicator"]][1])
keep <- rep(FALSE, length(dsi))
for (dataStateIndicatorThis in dataStateIndicator) {
keep <- keep | grepl(dataStateIndicatorThis, dsi , fixed=TRUE)
##> message(dataStateIndicatorThis)
##> print(keep)
}
x@data[[1]] <- x@data[[1]][keep]
x@processingLog <- oce::processingLogAppend(x@processingLog,
paste("subset argos type by dataStateIndicator=", dataStateIndicator))
} else if (dotsNames[1] == "dataMode") {
seeking <- dots$dataMode
# This testing of 'dataMode' may be overly complex
if (length(seeking) != 1)
stop("in subset,argoFloats-method(): length of 'dataMode' must be 1", call.=FALSE)
if (!seeking %in% c("realtime", "adjusted", "delayed"))
stop('in subset,argoFloats-method(): \'dataMode\' must be "realtime", "adjusted" or "delayed", not "', seeking, '"', call.=FALSE)
seeking <- switch(seeking, realtime="R", adjusted="A", delayed="D")
res <- x
a <- x@data$argos
for (i in seq_along(a)) {
A <- a[[i]]
keepProfile <- A[["dataMode"]] == seeking
#> message("i=", i, ", keepProfile=", paste(keepProfile, collapse=" "))
## flags
for (flagName in names(A@metadata$flags)) {
A@metadata$flags[[flagName]] <- A@metadata$flags[[flagName]][, keepProfile, drop=FALSE]
}
# dataMode
A@metadata$dataMode <- A@metadata$dataMode[keepProfile, drop=FALSE]
# data
for (dataName in names(A@data)) {
if (is.vector(A@data[[dataName]])) {
#> message("subset ", dataName, " vector from ", paste(A@data[[dataName]], collapse=" "))
A@data[[dataName]] <- A@data[[dataName]][keepProfile]
#> message(" ... to ", paste(A@data[[dataName]], collapse=" "))
} else if (is.array(A@data[[dataName]])) {
A@data[[dataName]] <- A@data[[dataName]][, keepProfile, drop=FALSE]
}
}
res@data$argos[[i]] <- A
}
res@processingLog <- oce::processingLogAppend(res@processingLog, paste(deparse(match.call()), sep="", collapse=""))
argoFloatsDebug(debug, "} # subset,argoFloats-method()\n", style="bold", sep="", unindent=1)
return(res)
} else {
stop("in subset,argoFloats-method():\n the \"...\" argument \"", dotsNames[1], "\" is not permitted for an argos-type object. The only valid choices are \"cycle\", \"dataMode\", \"ID\", \"dataSateIndicator\" and \"profile\".", call.=FALSE)
}
}
## Step 2: Now we know the type is either "index" or "profiles". In either case,
## "subset" can be provided, so we check for its existence first.
if (missing(subset)) {
#argoFloatsDebug(debug, "no subset was given, so it must be circle=, rectangle=, or similar\n")
if (length(dots) == 0)
stop("in subset,argoFloats-method() :\n for indices, must specify the subset, with \"subset\" argument, \"circle\",\"rectangle\", \"parameter\",\"polygon\", \"time\", \"institution\", \"deep\", \"ID\", \"ocean\", dataMode\", \"cycle\",\"direction\", or \"section\"", call.=FALSE)
if (length(dots) > 1)
stop("in subset,argoFloats-method() :\n cannot give more than one method in the \"...\" argument", call.=FALSE)
N <- length(x@data$index[[1]]) # used in calculating percentages
if (x@metadata$type == "index") {
istraj <- identical(x@metadata$subtype, "trajectories")
if (dotsNames[1] == "circle" && !istraj) {
argoFloatsDebug(debug, "subsetting an index by circle\n")
circle <- dots[[1]]
if (!is.list(dots[1]))
stop("in subset,argoFloats-method() :\n \"circle\" must be a list containing \"longitude\", \"latitude\" and \"radius\".", call.=FALSE)
if (3 != sum(c("longitude", "latitude", "radius") %in% sort(names(circle))))
stop("in subset,argoFloats-method() :\n \"circle\" must be a list containing \"longitude\", \"latitude\" and \"radius\"", call.=FALSE)
if (!requireNamespace("oce", quietly=TRUE))
stop("must install.packages(\"oce\") to subset by circle")
dist <- oce::geodDist(x[["longitude"]], x[["latitude"]], circle$longitude, circle$latitude)
keep <- dist < circle$radius
keep[is.na(keep)] <- FALSE
x@data$index <- x@data$index[keep, ]
x@processingLog <- oce::processingLogAppend(x@processingLog,
paste("subset index type by circle with longitude= ", circle$longitude, " , latitude= ", circle$latitude, ", and radius= ", circle$radius))
if (!silent)
message("Kept ", sum(keep), " cycles (", sprintf("%.3g", 100*sum(keep)/N), "%)")
} else if (dotsNames[1] == "circle" && istraj) {
stop("in subset,argoFloats-method(): cannot subset circle for \"index\" type with subtype = trajectories", call.=FALSE)
} else if (dotsNames[1] == "rectangle") {
argoFloatsDebug(debug, "subsetting an index by rectangle\n")
rectangle <- dots[[1]]
if (!is.list(dots[1]))
stop("in subset,argoFloats-method():\n \"rectangle\" must be a list containing \"longitude\" and \"latitude\"", call.=FALSE)
if (2 != sum(c("longitude", "latitude") %in% sort(names(rectangle))))
stop("in subset,argoFloats-method():\n \"rectangle\" must be a list containing \"longitude\" and \"latitude\"", call.=FALSE)
if (!istraj) {
keeplon <- rectangle$longitude[1] <=x[["longitude"]] & x[["longitude"]] <= rectangle$longitude[2]
keeplat <- rectangle$latitude[1] <= x[["latitude"]] & x[["latitude"]] <= rectangle$latitude[2]
ok <- is.finite(keeplon) & is.finite(keeplat)
keeplon[!ok] <- FALSE
keeplat[!ok] <- FALSE
keep <- keeplon & keeplat
} else if (istraj) {
if (!requireNamespace("sf", quietly=TRUE))
stop("must install sf package for subset(...,circle,...) to work with trajectory files")
sE <- rectangle$longitude[2]
sW <- rectangle$longitude[1]
sS <- rectangle$latitude[1]
sN <- rectangle$latitude[2]
s <- rbind(c(sW,sS), c(sW, sN), c(sE,sN), c(sE, sS), c(sW,sS))
S <- sf::st_polygon(list(s))
n <- nrow(x@data$index)
keep <- rep(FALSE, n)
for (i in seq_len(n)) {
#message("i equals ", i)
#print(x@data$index[i,])
tE <- as.numeric(x@data$index$longitude_max[i])
tW <- as.numeric(x@data$index$longitude_min[i])
tS <- as.numeric(x@data$index$latitude_min[i])
tN <- as.numeric(x@data$index$latitude_max[i])
t <- rbind(c(tW,tS), c(tW, tN), c(tE,tN), c(tE, tS), c(tW,tS))
T <- sf::st_polygon(list(t))
intersection <- sf::st_intersection(T, S)
keep[i] <- length(intersection) > 0
#print(intersects)
#message('intersects ', length(intersects) > 0)
}
}
x@data$index <- x@data$index[keep, ]
x@processingLog <- oce::processingLogAppend(x@processingLog,
paste("subset index type by rectangle with longitude= ", rectangle$longitude, " and latitude= ", rectangle$latitude ))
if (!silent)
message("Kept ", sum(keep), " cycles (", sprintf("%.3g", 100*sum(keep)/N), "%)")
} else if (dotsNames[1] == "parameter") {
argoFloatsDebug(debug, "subsetting an index by parameter\n")
parameter <- dots[[1]]
if (is.list(dots[1]))
parameters <- unlist(parameter)
nparameters <- length(parameters)
parametersList <- lapply(x[["parameters"]], function(p) strsplit(p, " ")[[1]])
keep <- unlist(lapply(parametersList, function(pl) nparameters == sum(parameters %in% pl)))
#if (sum(keep) < 1)
#warning("in subset,argoFloats-method(..., parameter):\n found no profiles with given parameter", call.=FALSE)
if (!silent && !istraj) {
message("Kept ", sum(keep), " cycles (", sprintf("%.3g", 100*sum(keep)/N), "%)")
} else if (!silent && istraj) {
message("Kept ", sum(keep), " trajectories (", sprintf("%.3g", 100*sum(keep)/N), "%)")
}
x@data$index <- x@data$index[keep, ]
x@processingLog <- oce::processingLogAppend(x@processingLog,
paste("subset index type by parameter= ",parameter))
} else if (dotsNames[1] == "polygon" && !istraj) {
argoFloatsDebug(debug, "subsetting an index by polygon\n")
if (!requireNamespace("sf", quietly=TRUE))
stop("must install.packages(\"sf\") for subset() by polygon to work")
polygon <- dots[[1]]
if(!is.list(dots[1]))
stop("in subset,argoFloats-method():\n \"polygon\" must be a list", call.=FALSE)
if (length(polygon) != 2)
stop("in subset,argoFloats-method():\n \"polygon\" must be a list of two elements", call.=FALSE)
if (2 != sum(c("longitude", "latitude") %in% names(polygon)))
stop("in subset,argoFloats-method():\n \"polygon\" must be a list containing \"longitude\" and \"latitude\"", call.=FALSE)
plat <- polygon$latitude
plon <- polygon$longitude
if (!length(plat) > 2)
stop("Must give at least three latitude coordinates.")
if (!length(plon) > 2)
stop("Must give at least three longitude coordinates.")
if (length(plat) != length(plon))
stop("lengths of polygon$longitude and polygon$latitude must match, but they are ",
length(plat), " and ", length(plon))
if ((head(plon, 1) != tail(plon, 1)) || head(plat, 1) != tail(plat, 1)) {
#warning("In subset,argoFloats-method(): Closing the polygon, since the first and last points did not match.\n", call.=FALSE)
plon <- c(plon, plon[1])
plat <- c(plat, plat[1])
}
alon <- x[["longitude"]]
alat <- x[["latitude"]]
## We need the *index* of points to keep, and not just a lon-lat subset of
## points. It is not too difficult to get the index with the sp
## package, but the only solution I could come up with using the sf
## package is to tack 1,2,3,etc onto the lon-lat points as a third
## dimension, so that after we select for the points inside, we can skim
## that third dimension and that gives us the keep value that we need. There
## may be a more straightforward way, but my (admittedly shallow) reading
## of the sf function list did not uncover anything promising, and my
## tests show that this scheme works.
##
## See https://github.com/ArgoCanada/argoFloats/issues/86
ok <- is.finite(alon) & is.finite(alat)
if (!requireNamespace("sf", quietly=TRUE))
stop("must install sf package for subset(...,polygon,...) to work")
Polygon <- sf::st_polygon(list(outer=cbind(plon, plat, rep(0, length(plon)))))
## DOES NOT WORK (REQUIRES OTHER SOFTWARE??): Polygon <- sf::st_make_valid(Polygon)
if (!is.finite(sf::st_is_valid(Polygon))) {
errorMessage <- sf::st_is_valid(Polygon, reason=TRUE)
stop(paste0("Error in subset,argoFloats-method():\n polygon is invalid, because of ", errorMessage), call.=FALSE)
}
## multipoint does not permit NA values, so we set them to zero and remove them later
Points <- sf::st_multipoint(cbind(ifelse(ok, alon, 0),
ifelse(ok, alat, 0),
seq_along(alon)))
if (!sf::st_is_valid(Points)) {
errorMessage <- sf::st_is_valid(Points, reason=TRUE)
stop(paste0("Error in subset,argoFloats-method():\n \"Points\" is invalid, because of ", errorMessage), call.=FALSE)
}
Intersection <- sf::st_intersection(Points, Polygon)
keep <- Intersection[,3]
if (!silent)
message("Kept ", length(keep), " cycles (", sprintf("%.3g", 100*length(keep)/N), "%)")
x@data$index <- x@data$index[keep, ]
x@processingLog <- oce::processingLogAppend(x@processingLog,
paste("subset index type by polygon"))
} else if (dotsNames[1] == "polygon" && istraj) {
stop("in subset,argoFloats-method(): cannot subset polygon for \"index\" type with subtype = trajectories", call.=FALSE)
} else if (dotsNames[1] == "time") {
argoFloatsDebug(debug, "subsetting an index by time\n")
time <- dots[[1]]
if(!is.list(dots[1]))
stop("in subset,argoFloats-method():\n \"time\" must be a list", call.=FALSE)
if (2 != sum(c("from", "to") %in% names(time)))
stop("in subset,argoFloats-method():\n \"time\" must be a list containing \"to\"and \"from\"", call.=FALSE)
if (length(time$from) != 1)
stop("from must be of length 1")
if (length(time$to) != 1)
stop("to must be of length 1")
if (!inherits(time$from, "POSIXt")) {
time$from <- try(as.POSIXct(time$from, tz="UTC"))
if (inherits(time$from, "try-error"))
stop("in subset,argoFloats-method():\n cannot convert \"time$from\" to a POSIX time", call.=FALSE)
}
if (!inherits(time$to, "POSIXt")) {
time$to <- try(as.POSIXct(time$to, tz="UTC"))
if (inherits(time$to, "try-error"))
stop("in subset,argoFloats-method():\n cannot convert \"time$to\" to a POSIX time", call.=FALSE)
}
if (time$to <= time$from)
stop ("in subset,argoFloats-method():\n \"to\" must be greater than \"from\"", call.=FALSE)
argoFloatsDebug(debug, "from= ", format(time$from, "%Y-%m-%d %H:%M:%S %z"), "\n")
argoFloatsDebug(debug, "to= ", format(time$to, "%Y-%m-%d %H:%M:%S %z"), "\n")
keep <- time$from[1] <= x[["date"]] & x[["date"]] <= time$to[1]
keep[is.na(keep)] <- FALSE
if (!silent && !istraj) {
message("Kept ", sum(keep), " cycles (", sprintf("%.3g", 100*sum(keep)/N), "%)")
} else if (!silent &&istraj) {
message("Kept ", sum(keep), " trajectories (", sprintf("%.3g", 100*sum(keep)/N), "%)")
}
x@data$index <- x@data$index[keep, ]
x@processingLog <- oce::processingLogAppend(x@processingLog,
paste("subset index type by time from", time$from, "to ", time$to))
} else if(dotsNames[1] == "institution") {
argoFloatsDebug(debug, "subsetting an index by institution\n")
institution <- dots[[1]]
if(!is.list(dots[1]))
stop("in subset,argoFloats-method():\n \"institution\" must be a list")
if (length(institution) > 1)
stop("\"institution\" cannot hold more than one element")
keep <- grepl(institution, x@data$index$institution)
keep[is.na(keep)] <- FALSE
if (!silent && !istraj) {
message("Kept ", sum(keep), " cycles (", sprintf("%.3g", 100*sum(keep)/N), "%)")
} else if (!silent && istraj) {
message("Kept ", sum(keep), " trajectories (", sprintf("%.3g", 100*sum(keep)/N), "%)")
}
x@data$index <- x@data$index[keep, ]
x@processingLog <- oce::processingLogAppend(x@processingLog,
paste("subset index type by institution " ,institution))
} else if (dotsNames[1] == "deep") {
argoFloatsDebug(debug, "subsetting an index by deep category\n")
deep <- dots[[1]]
if (!is.logical(deep))
stop("in subset,argoFloats-method():\n deep must be a logical vector indicating TRUE or FALSE", call.=FALSE)
if (deep) {
keep <- grep("849|862|864", x@data$index$profiler_type)
} else {
keep <- grep("849|862|864", x@data$index$profiler_type, invert=TRUE)
}
if (!silent && !istraj) {
message("Kept ", length(keep), " cycles (", sprintf("%.3g", 100*length(keep)/N), "%)")
} else if (!silent && istraj) {
message("Kept ", length(keep), " trajectories (", sprintf("%.3g", 100*length(keep)/N), "%)")
}
x@data$index <- x@data$index[keep, ]
x@processingLog <- oce::processingLogAppend(x@processingLog,
paste("subset index type to only include deep data"))
} else if (dotsNames[1] == "ID") {
argoFloatsDebug(debug, "subsetting an index by ID\n")
ID <- as.character(dots[[1]]) # convert in case it is numeric
xID <- x[["ID"]]
keep <- rep(FALSE, length(xID))
file <- x@data$index$file
for (thisID in ID)
keep <- keep | grepl(thisID, xID)
if (!silent && !istraj) {
message("Kept ", sum(keep), " cycles (", sprintf("%.3g", 100*sum(keep)/N), "%)")
} else if (!silent && istraj) {
message("Kept ", sum(keep), " trajectories (", sprintf("%.3g", 100*sum(keep)/N), "%)")
}
x@data$index <- x@data$index[keep, ]
x@processingLog <- oce::processingLogAppend(x@processingLog,
paste("subset index type by float ID", ID))
} else if (dotsNames[1] == "ocean" && !istraj) {
argoFloatsDebug(debug, "subsetting an index by ocean\n")
ocean <- dots[[1]]
if (!is.character(ocean))
stop("in subset,argoFloats-method() : \"ocean\" must be character value", call.=FALSE)
if (length(ocean) > 1)
stop("in subset,argoFloats-method():\n \"ocean\" cannot hold more than one element", call.=FALSE)
keep <- grepl(ocean, x@data$index$ocean)
keep[is.na(keep)] <- FALSE
if (!silent)
message("Kept ", sum(keep), " cycles (", sprintf("%.3g", 100.0*sum(keep)/N), "%)")
x@data$index <- x@data$index[keep, ]
x@processingLog <- oce::processingLogAppend(x@processingLog,
paste("subset index type by ocean", ocean))
} else if (dotsNames[1] == "ocean" && istraj) {
stop("in subset,argoFloats-method(): cannot subset ocean for \"index\" type with subtype = trajectories", call.=FALSE)
} else if (dotsNames[1] == "dataMode") {
argoFloatsDebug(debug, "subsetting an index by dataMode\n")
dataMode <- dots[[1]]
if (!is.character(dataMode))
stop("in subset,argoFloats-method():\n \"dataMode\" must be character value",call.=FALSE)
if (dataMode == "delayed" && !istraj) {
keep <- grepl("^[a-z]*/[0-9]*/profiles/.{0,1}D.*$", x[["file"]])
} else if (dataMode == "delayed" && istraj) {
keep <- grepl("^[a-z]*/[0-9]*/[0-9]*_.{0,1}D.*$", x[["file"]])
} else if (dataMode == "realtime" && !istraj) {
keep <- grepl("^[a-z]*/[0-9]*/profiles/.{0,1}R.*$", x[["file"]])
} else if (dataMode == "realtime" && istraj) {
keep <- grepl("^[a-z]*/[0-9]*/[0-9]*_.{0,1}R.*$", x[["file"]])
} else {
stop("in subset,argoFloats-method():\n \"dataMode\" must be either \"realtime\" or \"delayed\", not \"", dataMode, "\"", call.=FALSE)
}
if (!silent && !istraj) {
message("Kept ", sum(keep), " cycles (", sprintf("%.3g", 100.0*sum(keep)/N), "%)")
} else if (!silent && istraj) {
message("Kept ", sum(keep), " trajectories (", sprintf("%.3g", 100.0*sum(keep)/N), "%)")
}
x@data$index <- x@data$index[keep, ]
x@processingLog <- oce::processingLogAppend(x@processingLog,
paste("subset index type by dataMode", dataMode))
} else if (dotsNames[1] == "cycle" && !istraj) {
cycle <- dots[[1]]
if (!is.character(cycle) & !is.numeric(cycle))
stop("in subset,argoFloats-method() : \"cycle\" must be character value or numeric value", call.=FALSE)
## Calculate 'keep', a logical vector that will be used for the actual subsetting.
xcycle <- x[["cycle"]]
# If cycle is numeric, we must convert it to character (so e.g. 1 becomes "001")
if (is.numeric(cycle)) {
cycle <- sprintf("%03d", as.integer(cycle))
argoFloatsDebug(debug, "subsetting an index by cycle of numeric type\n")
} else if (is.character(cycle)) {
argoFloatsDebug(debug, "subsetting an index by cycle of character type\n")
} else {
stop("cycle must be character or numeric")
}
keep <- rep(FALSE, length(xcycle))
for (thisCycle in cycle)
keep <- keep | grepl(thisCycle, xcycle)
nkeep <- sum(keep)
if (nkeep < 1)
warning("In subset,argoFloats-method(..., parameter) : found no profiles with given cycle(s)", call.=FALSE)
if (!silent)
message("Kept ", nkeep, " cycles (", sprintf("%.3g", 100*nkeep/N), "%)")
x@data$index <- x@data$index[keep, ]
x@processingLog <- oce::processingLogAppend(x@processingLog,
paste("subset index type by cycle=", cycle))
} else if (dotsNames[1] == "cycle" && istraj) {
stop("in subset,argoFloats-method(): cannot subset cycle for \"index\" type with subtype = trajectories", call.=FALSE)
} else if (dotsNames[1] == "direction" && !istraj) {
argoFloatsDebug(debug, "subsetting an index by direction\n")
direction <- dots[[1]]
if (!is.character(direction))
stop("in subset,argoFloats-method():\n \"direction\" must be character value of either \"ascent\" or \"descent\"", call.=FALSE)
if (direction == "ascent") {
keep <- grepl("^.*[^D].nc$", x@data$index$file)
} else if (direction == "descent") {
keep <- grepl("^.*D.nc$", x@data$index$file)
} else {
stop("in subset,argoFloats-method():\n \"direction\" must be either \"ascent\" or \"descent\", not \"", direction, "\"", call.=FALSE)
}
x@data$index <- x@data$index[keep, ]
x@processingLog <- oce::processingLogAppend(x@processingLog,
paste("subset index type by direction=", direction))
} else if (dotsNames[1] == "direction" && istraj) {
stop("in subset,argoFloats-method(): cannot subset direction for \"index\" type with subtype = trajectories", call.=FALSE)
} else if (dotsNames[1] == "section" && !istraj) {
# The following link shows a test of this method.
# https://github.com/ArgoCanada/argoFloats/issues/397#issuecomment-798960312
if (!requireNamespace("s2", quietly=TRUE))
stop("must install.packages(\"s2\") to subset by section")
argoFloatsDebug(debug, "subsetting an index by section\n")
section <- dots[[1]]
if (!is.list(section))
stop("in subset,argoFloats-method() :\n section must be a list containing \"longitude\", \"latitude\" and possibly \"width\" and \"segments\"", call.=FALSE)
# Handle mandatory components
if (!"longitude" %in% names(section))
stop("in subset,argoFloats-method() :\n section must have a \"longitude\" entry", call.=FALSE)
if (!"latitude" %in% names(section))
stop("in subset,argoFloats-method() :\n section must have a \"latitude\" entry", call.=FALSE)
if (length(section$longitude) != length(section$latitude))
stop("in subset,argoFloats-method() :\n length of section$longitude (",
length(section$longitude), ") and section$latitude (", length(section$latitude), ") disagree", call.=FALSE)
# Handle optional components
if (!"width" %in% names(section))
section$width <- 100
if (!"segments" %in% names(section))
section$segments <- 100
if (!is.null(section$segments)) {
if (!is.numeric(section$segments) || section$segments > 0) {
argoFloatsDebug(debug, "subdividing lon,lat trace (of length ", length(section$longitude), ") to increase length to ", section$segments, "\n", sep="")
s <- seq(0, 1, length.out=length(section$longitude))
section$longitude <- stats::approx(s, section$longitude, seq(0, 1, length.out=section$segments))$y
section$latitude <- stats::approx(s, section$latitude, seq(0, 1, length.out=section$segments))$y
} else {
stop("in subset,argoFloats-method() :\n section$segments must be NULL or a positive integer", call.=FALSE)
}
}
# Create a spine for the section.
sectionSpine <- s2::s2_make_line(section$longitude, section$latitude)
# Create points for float locations. Blank the NAs, in case not allowed.
alon <- x[["longitude"]]
alat <- x[["latitude"]]
bad <- !is.finite(alon) | !is.finite(alat)
alon[bad] <- 0
alat[bad] <- 0
floatLocations <- s2::as_s2_geography(s2::s2_lnglat(alon, alat))
# Identify floats near the section spine
keep <- s2::s2_dwithin(floatLocations, sectionSpine, 1000*section$width)
argoFloatsDebug(debug, "sum(keep)=", sum(keep), " i.e. ",
round(100*sum(keep)/length(keep), 3), "% (before accounting for NA values)\n", sep="")
keep <- keep & !bad
argoFloatsDebug(debug, "sum(keep)=", sum(keep), " i.e. ",
round(100*sum(keep)/length(keep), 3), "% (after accounting for NA values)\n", sep="")
if (!silent)
message("Kept ", sum(keep), " cycles (", sprintf("%.3g", 100*sum(keep)/N), "%)")
x@data$index <- x@data$index[keep, ]
x@processingLog <- oce::processingLogAppend(x@processingLog,
paste0("subset index type by section with longitude=c(",
paste(section$longitude, collapse=", "), "), latitude=c(",
paste(section$latitude, collapse=", "), "), and width=",
section$width, " km"))
} else if (dotsNames[1] == "section" && istraj) {
stop("in subset,argoFloats-method(): cannot subset section for \"index\" type with subtype = trajectories", call.=FALSE)
} else {
stop("in subset,argoFloats-method():\n the \"...\" argument \"", dotsNames[1], "\" is not permitted for an index-type object. The only valid choices are \"circle\", \"rectangle\", \"parameter\", \"polygon\", \"time\", \"institution\", \"deep\", \"ID\", \"ocean\", \"dataMode\", \"cycle\",\"direction\" and \"section\"", call.=FALSE)
}
}
} else {
## subset is not missing
if (length(dotsNames) != 0)
stop("in subset,argoFloats-method():\n cannot give both \"subset\" and \"...\" arguments", call.=FALSE)
if (x@metadata$type == "index") {
if (!silent) {
if (is.logical(subset)) # this simplifies the percentage count for the method
subset <- which(subset)
message("Kept ", length(subset), " cycles (", sprintf("%.3g", 100.0*length(subset)/dim(x@data$index)[1]), "%)")
}
x@data$index <- x@data$index[subset, ]
} else {
stop("in subset,argoFloats-method():\n method not coded except for type=\"index\"", call.=FALSE)
}
}
argoFloatsDebug(debug, "} # subset,argoFloats-method()\n", style="bold", sep="", unindent=1)
x
})
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.