diff --git a/NEWS b/NEWS index e5852d37..44e4518d 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,32 @@ poppr 2.8.0 =========== +BUG FIX +------- + +* `win.ia()` now has more consistent behavior with chromosome structure and will + no longer result in an integer overflow + (see https://github.com/grunwaldlab/poppr/issues/179). + +ALGORITHMIC CHANGE +------------------ + +* `win.ia()` may result in slightly different results because of two changes: + 1. The windows will now always start at position one on any given chromosome. + This will result in some windows at the beginning of chromosomes having a + value of `NA` if the first variant starts beyond the first window. + 2. Windows are now calculated for each chromosome independently. The previous + version first concatenated chromosomes with at least a window-sized gap + between the chromosomes, but failed to ensure that the window always started + at the beginning of the chromosome. This version fixes that issue. + (see https://github.com/grunwaldlab/poppr/issues/179). + +DEPRECATION +----------- + +* The `chromosome_buffer` argument for `win.ia()` has been permanently set to + `TRUE` and deprecated as it is no longer used. + NEW FEATURES ------------ diff --git a/man/win.ia.Rd b/man/win.ia.Rd index 4aaea60a..0cb1a9b3 100644 --- a/man/win.ia.Rd +++ b/man/win.ia.Rd @@ -8,40 +8,39 @@ win.ia(x, window = 100L, min.snps = 3L, threads = 1L, quiet = FALSE, chromosome_buffer = TRUE) } \arguments{ -\item{x}{a \code{\link{genlight}} or \code{\link{snpclone}} object.} +\item{x}{a \link[=genlight-class]{genlight} or \link[=snpclone-class]{snpclone} object.} \item{window}{an integer specifying the size of the window.} -\item{min.snps}{an integer specifying the minimum number of snps allowed per +\item{min.snps}{an integer specifying the minimum number of snps allowed per window. If a window does not meet this criteria, the value will return as -NA.} +\code{NA}.} -\item{threads}{The maximum number of parallel threads to be used within this -function. A value of 0 (default) will attempt to use as many threads as -there are available cores/CPUs. In most cases this is ideal. A value of 1 -will force the function to run serially, which may increase stability on -some systems. Other values may be specified, but should be used with -caution.} +\item{threads}{The maximum number of parallel threads to be used within this +function. Defaults to 1 thread, in which the function will run serially. A +value of 0 will attempt to use as many threads as there are available +cores/CPUs. In most cases this is ideal for speed. Note: this option is +passed to \code{\link[=bitwise.ia]{bitwise.ia()}} and does not parallelize the windowization process.} -\item{quiet}{if \code{FALSE}, a progress bar will be printed to the screen.} +\item{quiet}{if \code{FALSE} (default), a progress bar will be printed to the screen.} -\item{chromosome_buffer}{if \code{TRUE} (default), buffers will be placed +\item{chromosome_buffer}{\emph{DEPRECATED} if \code{TRUE} (default), buffers will be placed between adjacent chromosomal positions to prevent windows from spanning two chromosomes.} } \value{ -Index of association representing the samples in this genlight - object. +A value of the standardized index of association for all windows in +each chromosome. } \description{ -Genlight objects can contain millions of loci. Since it does not make much +Genlight objects can contain millions of loci. Since it does not make much sense to calculate the index of association over that many loci, this function will scan windows across the loci positions and calculate the index of association. } \note{ this will calculate the standardized index of association from Agapow -2001. See \code{\link{ia}} for details. +and Burt, 2001. See \code{\link[=ia]{ia()}} for details. } \examples{ @@ -73,7 +72,6 @@ plot(res, type = "l") library("dplyr") res_tidy <- res \%>\% data_frame(rd = ., chromosome = names(.)) \%>\% # create two column data frame - filter(chromosome != "") \%>\% # filter out null chromosomes group_by(chromosome) \%>\% # group data by chromosome mutate(window = row_number()) \%>\% # windows by chromosome ungroup(chromosome) \%>\% # ungroup and reorder @@ -93,11 +91,7 @@ ggplot(res_tidy, aes(x = window, y = rd, color = chromosome)) + } \seealso{ -\code{\link[adegenet]{genlight}}, - \code{\link{snpclone}}, - \code{\link{samp.ia}}, - \code{\link{ia}}, - \code{\link{bitwise.dist}} +\link[=genlight-class]{genlight}, \link[=snpclone-class]{snpclone}, \code{\link[=ia]{ia()}}, \code{\link[=samp.ia]{samp.ia()}}, \code{\link[=bitwise.dist]{bitwise.dist()}} } \author{ Zhian N. Kamvar, Jonah C. Brooks diff --git a/tests/testthat/test-winia.R b/tests/testthat/test-winia.R index 42ce95bb..91547ace 100644 --- a/tests/testthat/test-winia.R +++ b/tests/testthat/test-winia.R @@ -1,41 +1,44 @@ context("win.ia tests") -options(poppr.debug = FALSE) set.seed(999) chrom_pos <- vapply(1:10, function(i) sort(sample(1e3, 100)), integer(100)) %>% as.vector() chromo <- rep(1:10, each = 100) -real_pos <- chrom_pos + 1000*(chromo - 1) + 1#+ 100*(chromo - 1) + 1 set.seed(999) x <- glSim(n.ind = 10, n.snp.nonstruc = 5e2, n.snp.struc = 5e2, ploidy = 2, parallel = FALSE) test_that("win.ia will throw an error if duplicate positions are found", { - x.naive <- win.ia(x) + options(poppr.debug = TRUE) + expect_output(x.naive <- win.ia(x), "[|=]{2,}") position(x) <- chrom_pos expect_equal(length(x.naive), 10L) expect_error(win.ia(x), "chromosome") + options(poppr.debug = FALSE) }) +test_that("win.ia will throw a warning if chromosome_buffer is specified", { + expect_warning(x.naive <- win.ia(x, quiet = TRUE, chromosome_buffer = FALSE), "deprecated") +}) + test_that("win.ia will use chromosome structure", { skip_on_cran() position(x) <- chrom_pos chromosome(x) <- chromo - x.chrom.bt <- win.ia(x) - expect_equal(sum(is.na(x.chrom.bt) & !is.nan(x.chrom.bt)), 9L) - expect_equal(length(x.chrom.bt), 109L) + x.chrom.bt <- win.ia(x, quiet = TRUE) + expect_equal(length(x.chrom.bt), 100L) + expect_equal(names(x.chrom.bt), as.character(rep(1:10, each = 10))) }) -test_that("win.ia will take into account chromosome buffer", { +test_that("win.ia will always start at the beginning of the chromosome", { skip_on_cran() position(x) <- chrom_pos chromosome(x) <- chromo - x.chrom.bf <- win.ia(x, chromosome_buffer = FALSE) - chromosome(x) <- NULL - position(x) <- real_pos - x.real <- win.ia(x) - expect_equal(length(x.chrom.bf), 100L) - expect_equal(length(x.chrom.bf), length(x.real)) - expect_equal(x.chrom.bf, x.real, check.attributes = FALSE) + x.chrom.bf <- win.ia(x, window = 300L, quiet = TRUE) + x.by.chrom <- lapply(levels(chromosome(x)), function(i) win.ia(x[, chromosome(x) == i], window = 300L, quiet = TRUE)) + # There should be 4 windows per chromosome. + expect_equal(length(x.chrom.bf), 40L) + # Using the function with and without chromosome structure should not matter. + expect_equal(x.chrom.bf, unlist(x.by.chrom, use.names = FALSE), check.attributes = FALSE) + }) -