From 643715ed0071cb8737df84875c5d2d96fa0922cc Mon Sep 17 00:00:00 2001 From: Won June Tai Date: Mon, 20 Mar 2017 20:01:34 -0400 Subject: [PATCH 1/7] Beginning importFilterHypermutators task --- R/importFilterHypermutators.R | 101 ++++++++++++++++++++++++++++++++++ tests/testthat/testFilter.R | 24 ++++++++ 2 files changed, 125 insertions(+) create mode 100644 R/importFilterHypermutators.R create mode 100644 tests/testthat/testFilter.R diff --git a/R/importFilterHypermutators.R b/R/importFilterHypermutators.R new file mode 100644 index 0000000..f653cf8 --- /dev/null +++ b/R/importFilterHypermutators.R @@ -0,0 +1,101 @@ +# importFilterHypermutators.R + +#' Filters out hypermutators +#' +#' \code{importFilterHypermutators} identifies the number of SNV and CNA +#' mutations for each sample and removes the samples from rMUT and rCNA +#' datasets. Default threshold for removal is 400 mutations per sample. +#' +#' @param fNames A vector of local file names of rMUT and/or rCNA files +#' @param dOut Directory to store output, defaults to getwd(). +#' @param xS Mutation threshold. 400 by default. +#' @param silent Controls whether output to console should be suppressed. FALSE +#' by default. +#' @param writeLog Controls whether writing the result to the global logfile is +#' enabled. TRUE by default. +#' +#' @examples +#' \dontrun{ +#' importFilterHypermutators(fNames, dOut, xS) +#' } +#' +#' @export +importFilterHypermutators <- function(fNames = c(), + dOut = getwd(), + xS = 400, + silent = FALSE, + writeLog = TRUE) { + + ## VALIDATE PARAMS ######## + # make sure that files actually exist + for (file in fNames) { + r <- .checkArgs(file, like = "FILE_E", checkSize = TRUE) + if (length(r) > 0) { + stop(sprintf("Local file name %s is invalid.", file)) + } + } + + # make sure that output directory is valid + r <- .checkArgs(fPath, like = "DIR", checkSize = TRUE) + if(length(r) > 0) { + stop(sprintf("Output directory %s is invalid.", dOut)) + } + + # make sure that xS is valid double + r <- .checkArgs(xS, like = "double", checkSize = TRUE) + if (length(r) > 0) { + stop(xS) + } + + + # set up hash + hashTable <- new.env(hash = TRUE) + totalRemovedSamples <- 0 + totalSamples <- 0 + + ## COUNT MUTATIONS ######## + # for each file in fNames, + # determine if it is rMUT or rCNA + # process rCNA files first + # if rCNA: read file, count # of gene-CNAs for each sample, store + # if rMUT: read file, if key not in hash then create + # increment counter of nMUT in sample's value + + ## ASSESS MUTATIONS ####### + # for each key in hash, set boolean thrsh <- TRUE if nMUT + nCNA > xS + + ## PROCESS FILES ########## + + # for each requested data file: + # determine if rMUT or rCNA + # if rCNA: read, remove columns where thrsh == TRUE, write file + # if rMUT: read, do the same for new file + + ## LOGGING ############### + + if(writeLog) { + + logTitle <- "importFilterHypermutators" + + # Compile function call record + logCall <- character() + logCall[1] <- "importFilterHypermutators(" + logCall[2] <- sprintf("fNames = \"%s\", ", fNames) + logCall[3] <- sprintf("dOut = \"%s\", ", dOut) + logCall[4] <- sprintf("xS = \"%s\", ", as.character(xS)) + logCall[8] <- sprintf("silent = %s, ", as.character(silent)) + logCall[9] <- sprintf("writeLog = %s)", as.character(writeLog)) + logCall <- paste0(logCall, collapse = "") + + # Record progress information + logNotes <- character() + logNotes <- c(logNotes, sprintf("Removed %s of %s samples", totalRemovedSamples, totalSamples)) + + # # send info to log file + logEvent(eventTitle = logTitle, + eventCall = logCall, + notes = logNotes) + } + + # returns nothing +} diff --git a/tests/testthat/testFilter.R b/tests/testthat/testFilter.R new file mode 100644 index 0000000..7930302 --- /dev/null +++ b/tests/testthat/testFilter.R @@ -0,0 +1,24 @@ +# testFilter.R + +context("Tests for importFilterHypermutators.R") + +# set up a tempdir and tempfiles for outputs of importFilterHypermutators + +test_that("importFilterHypermutators rejects invalid fName arguments", { + # check for including NULL objects + # check for including filenames that don't exist +}) + +test_that("importFilterHypermutators rejects invalid dOut arguments", { + # check for NULL object + # check for paths that don't exist +}) + +test_that("importFilterHypermutators rejects invalid xS arguments", { + # check for including NULL objects +}) + +test_that("importFilterHypermutators correctly removes hypermutators", { + # run importFilterHypermutators + # check output file +}) From 56d84f18432ff941bb603421ca573e21e5e3cc8e Mon Sep 17 00:00:00 2001 From: Won June Tai Date: Sat, 25 Mar 2017 00:22:14 -0400 Subject: [PATCH 2/7] Address some comments * Also adds new test .RDS files for devSNV and devCNA --- NAMESPACE | 1 + R/importFilterHypermutators.R | 164 ++++++++++++++++++++++++------- inst/extdata/devCNA.rds | Bin 0 -> 20948 bytes inst/extdata/devSNV.rds | Bin 0 -> 1189 bytes man/importFilterHypermutators.Rd | 33 +++++++ tests/testthat/testFilter.R | 61 ++++++++++-- 6 files changed, 217 insertions(+), 42 deletions(-) create mode 100644 inst/extdata/devCNA.rds create mode 100644 inst/extdata/devSNV.rds create mode 100644 man/importFilterHypermutators.Rd diff --git a/NAMESPACE b/NAMESPACE index 1cdf9f5..97d21ee 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -8,6 +8,7 @@ export(fastMapUpdate) export(findUUID) export(getProvenance) export(getUUID) +export(importFilterHypermutators) export(importNet.STRING) export(logEvent) export(logFileName) diff --git a/R/importFilterHypermutators.R b/R/importFilterHypermutators.R index f653cf8..e4677cd 100644 --- a/R/importFilterHypermutators.R +++ b/R/importFilterHypermutators.R @@ -3,73 +3,152 @@ #' Filters out hypermutators #' #' \code{importFilterHypermutators} identifies the number of SNV and CNA -#' mutations for each sample and removes the samples from rMUT and rCNA +#' mutations for each sample and removes the samples from rSNV and rCNA #' datasets. Default threshold for removal is 400 mutations per sample. #' -#' @param fNames A vector of local file names of rMUT and/or rCNA files +#' @param rSNVFileIn A vector of local file names of rSNV +#' @param rCNAFileIn A vector of local file names of rCNA #' @param dOut Directory to store output, defaults to getwd(). #' @param xS Mutation threshold. 400 by default. #' @param silent Controls whether output to console should be suppressed. FALSE #' by default. #' @param writeLog Controls whether writing the result to the global logfile is #' enabled. TRUE by default. +#' @param writeDetailedLog Flag for extra details about log. TRUE by default. #' #' @examples #' \dontrun{ -#' importFilterHypermutators(fNames, dOut, xS) +#' importFilterHypermutators(rSNVFileIn, rCNAFileIn, dOut, xS) #' } #' #' @export -importFilterHypermutators <- function(fNames = c(), +importFilterHypermutators <- function(rSNVFileIn = c(), + rCNAFileIn = c(), dOut = getwd(), xS = 400, silent = FALSE, - writeLog = TRUE) { + writeLog = TRUE, + writeDetailedLog = TRUE) { ## VALIDATE PARAMS ######## # make sure that files actually exist - for (file in fNames) { + for (file in rSNVFileIn) { r <- .checkArgs(file, like = "FILE_E", checkSize = TRUE) if (length(r) > 0) { - stop(sprintf("Local file name %s is invalid.", file)) + stop(r) + } + } + + for (file in rCNAFileIn) { + r <- .checkArgs(file, like = "FILE_E", checkSize = TRUE) + if (length(r) > 0) { + stop(r) } } # make sure that output directory is valid - r <- .checkArgs(fPath, like = "DIR", checkSize = TRUE) + r <- .checkArgs(dOut, like = "DIR", checkSize = TRUE) if(length(r) > 0) { - stop(sprintf("Output directory %s is invalid.", dOut)) + stop(r) } - # make sure that xS is valid double - r <- .checkArgs(xS, like = "double", checkSize = TRUE) + r <- c(r, .checkArgs(xS, like = 1, checkSize = TRUE)) if (length(r) > 0) { - stop(xS) + stop(r) } - - # set up hash + # set up hashes hashTable <- new.env(hash = TRUE) - totalRemovedSamples <- 0 totalSamples <- 0 ## COUNT MUTATIONS ######## - # for each file in fNames, - # determine if it is rMUT or rCNA - # process rCNA files first - # if rCNA: read file, count # of gene-CNAs for each sample, store - # if rMUT: read file, if key not in hash then create - # increment counter of nMUT in sample's value + # for each file in rCNAFileIn + for (file in rCNAFileIn) { + # readRDS, count gene CNAs and add to hash for sample @ CNA and nMUT + rCNA <- readRDS(file) + for (sample in colnames(rCNA)) { + totalSamples <- totalSamples + 1 + # if key is in hash, increment CNA and nMUT + if (!is.null(hashTable$sample)) { + prevCNACount <- hashTable$sample$CNA + prevTotalCount <- hashTable$sample$total + assign(sample, list(CNA = prevCNACount + 1, SNV = 0, total = prevTotalCount + 1), envir = hashTable) + } + # question - does each gene-CNA count as one mutation? I'm guessing yes? + assign(sample, list(CNA = 1, SNV = 0, total = 1), envir = hashTable) + } + } - ## ASSESS MUTATIONS ####### - # for each key in hash, set boolean thrsh <- TRUE if nMUT + nCNA > xS + # for each file in rSNVFileIn + for (file in rSNVFileIn) { + # readRDS, increment counter for SNV and nMUT + rSNV <- readRDS(file) + for (sample in rSNV$Tumor_Sample_Barcode) { + # need to substitute dashes with period for consistency in files + sample <- gsub("-", ".", sample) + totalSamples <- totalSamples + 1 + # if key is in hash, increment SNV and nMUT + if (!is.null(hashTable$sample)) { + prevCNACount <- hashTable$sample$CNA + prevSNVCount <- hashTable$sample$SNV + prevTotalCount <- hashTable$sample$total + assign(sample, list(CNA = prevCNACount, SNV = prevSNVCount + 1, nMUT = prevTotalCount + 1), envir = hashTable) + } + assign(sample, list(CNA = 0, SNV = 1, total = 1), envir = hashTable) + } + } - ## PROCESS FILES ########## + ## ASSESS MUTATIONS AND LOG STATISTICS ####### + + # log global statistics: + numSamplesBothSNVAndCNA <- 0 + numSamplesOnlyCNA <- 0 + numSamplesOnlySNV <- 0 + numSamplesNoChange <- 0 + numSamplesExceedThresh <- 0 + numRemovedSamples <- 0 + removedSamples <- c() + + for (sample in ls(hashTable)) { + # num samples with only CNA + if (hashTable[[sample]]$SNV == 0) { + numSamplesOnlyCNA <- numSamplesOnlyCNA + 1 + } + # num samples with only SNV + else if (hashTable[[sample]]$CNA == 0) { + numSamplesOnlySNV <- numSamplesOnlySNV + 1 + } + # num samples with both SNV and CNA + else if (hashTable[[sample]]$CNA > 0 && hashTable[[sample]]$SNV > 0) { + numSamplesBothSNVAndCNA <- numSamplesBothSNVAndCNA + 1 + } + # num samples that exceeded threshold and need removal + else if (hashTable[[sample]]$total > xS) { + numRemovedSamples <- numRemovedSamples + 1 + removedSamples <- c(removedSamples, sample) + } + # num samples with no change + else { + numSamplesNoChange <- numSamplesNoChange + 1 + } + } + + ## PROCESS FILES AND UPDATE METADATA ########## - # for each requested data file: - # determine if rMUT or rCNA - # if rCNA: read, remove columns where thrsh == TRUE, write file - # if rMUT: read, do the same for new file + # for each rCNAFileIn + for (file in rCNAFileIn) { + # for each sample, if hashTable$sample$total > xS, remove it + # update metadata (getUUID(object)) + # save new CNAFile + } + + + # for each rSNVFileIn + for (file in rSNVFileIn) { + # for each sample (need to gsub("\.", "-", sample)), if hashTable$sample$total > xS, remove it + # update metadata (getUUID(object)) + # save new SNVFile + } ## LOGGING ############### @@ -80,16 +159,30 @@ importFilterHypermutators <- function(fNames = c(), # Compile function call record logCall <- character() logCall[1] <- "importFilterHypermutators(" - logCall[2] <- sprintf("fNames = \"%s\", ", fNames) - logCall[3] <- sprintf("dOut = \"%s\", ", dOut) - logCall[4] <- sprintf("xS = \"%s\", ", as.character(xS)) - logCall[8] <- sprintf("silent = %s, ", as.character(silent)) - logCall[9] <- sprintf("writeLog = %s)", as.character(writeLog)) + logCall[2] <- sprintf("rSNVFileIn = \"%s\", ", rSNVFileIn) + logCall[3] <- sprintf("rCNAFileIn = \"%s\", ", rCNAFileIn) + logCall[4] <- sprintf("dOut = \"%s\", ", dOut) + logCall[5] <- sprintf("xS = \"%s\", ", as.character(xS)) + logCall[6] <- sprintf("silent = %s, ", as.character(silent)) + logCall[7] <- sprintf("writeLog = %s)", as.character(writeLog)) logCall <- paste0(logCall, collapse = "") # Record progress information logNotes <- character() - logNotes <- c(logNotes, sprintf("Removed %s of %s samples", totalRemovedSamples, totalSamples)) + logNotes <- c(logNotes, sprintf("Removed %s of %s samples", numRemovedSamples, totalSamples)) + + if (writeDetailedLog) { + logNotes <- c(logNotes, sprintf("%s of samples had both SNV and CNA", numSamplesBothSNVAndCNA/totalSamples)) + logNotes <- c(logNotes, sprintf("%s of samples had only CNA", numSamplesOnlyCNA/totalSamples)) + logNotes <- c(logNotes, sprintf("%s of samples had only SNV", numSamplesOnlySNV/totalSamples)) + logNotes <- c(logNotes, sprintf("%s of samples had no change", numSamplesNoChange/totalSamples)) + logNotes <- c(logNotes, sprintf("%s of samples exceeded threshold of %s", numSamplesExceedThresh/totalSamples, xS)) + + # Accumulate all removed samples + for (sample in removedSamples) { + logNotes <- c(logNotes, sprintf("%s was removed", sample)) + } + } # # send info to log file logEvent(eventTitle = logTitle, @@ -97,5 +190,6 @@ importFilterHypermutators <- function(fNames = c(), notes = logNotes) } - # returns nothing } + +# [END] diff --git a/inst/extdata/devCNA.rds b/inst/extdata/devCNA.rds new file mode 100644 index 0000000000000000000000000000000000000000..9b5b6f7ca1a7088e9e39aeac9f24f335e4b34de2 GIT binary patch literal 20948 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

K`Zn6+7f}l+JWk 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 DA2&z> literal 0 HcmV?d00001 diff --git a/man/importFilterHypermutators.Rd b/man/importFilterHypermutators.Rd new file mode 100644 index 0000000..87e7771 --- /dev/null +++ b/man/importFilterHypermutators.Rd @@ -0,0 +1,33 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/importFilterHypermutators.R +\name{importFilterHypermutators} +\alias{importFilterHypermutators} +\title{Filters out hypermutators} +\usage{ +importFilterHypermutators(fNames = c(), dOut = getwd(), xS = 400, + silent = FALSE, writeLog = TRUE) +} +\arguments{ +\item{fNames}{A vector of local file names of rMUT and/or rCNA files} + +\item{dOut}{Directory to store output, defaults to getwd().} + +\item{xS}{Mutation threshold. 400 by default.} + +\item{silent}{Controls whether output to console should be suppressed. FALSE +by default.} + +\item{writeLog}{Controls whether writing the result to the global logfile is +enabled. TRUE by default.} +} +\description{ +\code{importFilterHypermutators} identifies the number of SNV and CNA +mutations for each sample and removes the samples from rMUT and rCNA +datasets. Default threshold for removal is 400 mutations per sample. +} +\examples{ +\dontrun{ + importFilterHypermutators(fNames, dOut, xS) +} + +} diff --git a/tests/testthat/testFilter.R b/tests/testthat/testFilter.R index 7930302..868cbfb 100644 --- a/tests/testthat/testFilter.R +++ b/tests/testthat/testFilter.R @@ -1,24 +1,71 @@ -# testFilter.R - +# testFilter +# +# context("Tests for importFilterHypermutators.R") -# set up a tempdir and tempfiles for outputs of importFilterHypermutators +# ==== BEGIN SETUP AND PREPARE ================================================= +OLOG <- as.character(getOption("rete.logfile")) # save original logfile name +logFileName(fPath = tempdir(), setOption = TRUE) # make tempdir() the log dir +logName <- unlist(getOption("rete.logfile")) +if (file.exists(logName)) { file.remove(logName)} +# ==== END SETUP AND PREPARE =================================================== -test_that("importFilterHypermutators rejects invalid fName arguments", { - # check for including NULL objects - # check for including filenames that don't exist + +# ==== importFilterHypermutators() ============================================= + +# set up a tempdir and tempfiles for outputs of importFilterHypermutators +test_that("importFilterHypermutators works correctly on valid input", { + # run importFilterHypermutators on valid input + expect_error(importFilterHypermutators(rSNVFileIn = c('../../inst/extdata/devSNV.rds'), + rCNAFileIn = c('../../inst/extdata/devCNA.rds'), + dOut = getwd(), + xS = 400, + silent = FALSE, + writeLog = TRUE), NA) }) test_that("importFilterHypermutators rejects invalid dOut arguments", { # check for NULL object + expect_error(importFilterHypermutators(rSNVFileIn = c('../../inst/extdata/devSNV.rds'), + rCNAFileIn = c('../../inst/extdata/devCNA.rds'), + dOut = NULL, + xS = 400, + silent = FALSE, + writeLog = TRUE)) # check for paths that don't exist + expect_error(importFilterHypermutators(rSNVFileIn = c('../../inst/extdata/devSNV.rds'), + rCNAFileIn = c('../../inst/extdata/devCNA.rds'), + dOut = 'no/such/path', + xS = 400, + silent = FALSE, + writeLog = TRUE)) }) test_that("importFilterHypermutators rejects invalid xS arguments", { # check for including NULL objects + expect_error(importFilterHypermutators(rSNVFileIn = c('../../inst/extdata/devSNV.rds'), + rCNAFileIn = c('../../inst/extdata/devCNA.rds'), + xS = NULL, + silent = FALSE, + writeLog = TRUE)) + # check character + expect_error(importFilterHypermutators(rSNVFileIn = c('../../inst/extdata/devSNV.rds'), + rCNAFileIn = c('../../inst/extdata/devCNA.rds'), + xS = "400", + silent = FALSE, + writeLog = TRUE)) }) test_that("importFilterHypermutators correctly removes hypermutators", { - # run importFilterHypermutators + # run importFilterHypermutators with a single hypermutator + # check output file }) + +# ==== BEGIN TEARDOWN AND RESTORE ============================================== +logName <- unlist(getOption("rete.logfile")) +if (file.exists(logName)) { file.remove(logName)} +options("rete.logfile" = OLOG) +# ==== END TEARDOWN AND RESTORE =============================================== + +# [END] From e2de46ee4c29e2d3aadb84389cf1415cd5521a48 Mon Sep 17 00:00:00 2001 From: Won June Tai Date: Mon, 27 Mar 2017 22:56:24 -0400 Subject: [PATCH 3/7] Addresses comments --- R/importFilterHypermutators.R | 63 ++++++++++++++++++++++++----------- tests/testthat/testFilter.R | 41 +++++++++++++++++------ 2 files changed, 74 insertions(+), 30 deletions(-) diff --git a/R/importFilterHypermutators.R b/R/importFilterHypermutators.R index e4677cd..e961e66 100644 --- a/R/importFilterHypermutators.R +++ b/R/importFilterHypermutators.R @@ -68,14 +68,18 @@ importFilterHypermutators <- function(rSNVFileIn = c(), rCNA <- readRDS(file) for (sample in colnames(rCNA)) { totalSamples <- totalSamples + 1 - # if key is in hash, increment CNA and nMUT - if (!is.null(hashTable$sample)) { - prevCNACount <- hashTable$sample$CNA - prevTotalCount <- hashTable$sample$total - assign(sample, list(CNA = prevCNACount + 1, SNV = 0, total = prevTotalCount + 1), envir = hashTable) + # if key is in hash, increment CNA and nMUT for every gene if there is an abberation + for (copyNumberValue in rCNA[[sample]]) { + if (copyNumberValue != 0) { + if (!is.null(hashTable[[sample]])) { + prevCNACount <- hashTable[[sample]]$CNA + prevTotalCount <- hashTable[[sample]]$total + assign(sample, list(CNA = prevCNACount + 1, SNV = 0, total = prevTotalCount + 1), envir = hashTable) + } else { + assign(sample, list(CNA = 1, SNV = 0, total = 1), envir = hashTable) + } + } } - # question - does each gene-CNA count as one mutation? I'm guessing yes? - assign(sample, list(CNA = 1, SNV = 0, total = 1), envir = hashTable) } } @@ -83,18 +87,25 @@ importFilterHypermutators <- function(rSNVFileIn = c(), for (file in rSNVFileIn) { # readRDS, increment counter for SNV and nMUT rSNV <- readRDS(file) - for (sample in rSNV$Tumor_Sample_Barcode) { + for (i in 1:length(rSNV$Tumor_Sample_Barcode)) { # need to substitute dashes with period for consistency in files - sample <- gsub("-", ".", sample) + sample <- gsub("-", ".", rSNV$Tumor_Sample_Barcode[i]) totalSamples <- totalSamples + 1 + + # Present a progress bar. + if (!silent) { + .pBar(i, length(rSNV$Tumor_Sample_Barcode)) + } + # if key is in hash, increment SNV and nMUT - if (!is.null(hashTable$sample)) { - prevCNACount <- hashTable$sample$CNA - prevSNVCount <- hashTable$sample$SNV - prevTotalCount <- hashTable$sample$total + if (!is.null(hashTable[[sample]])) { + prevCNACount <- hashTable[[sample]]$CNA + prevSNVCount <- hashTable[[sample]]$SNV + prevTotalCount <- hashTable[[sample]]$total assign(sample, list(CNA = prevCNACount, SNV = prevSNVCount + 1, nMUT = prevTotalCount + 1), envir = hashTable) + } else { + assign(sample, list(CNA = 0, SNV = 1, total = 1), envir = hashTable) } - assign(sample, list(CNA = 0, SNV = 1, total = 1), envir = hashTable) } } @@ -137,17 +148,29 @@ importFilterHypermutators <- function(rSNVFileIn = c(), # for each rCNAFileIn for (file in rCNAFileIn) { - # for each sample, if hashTable$sample$total > xS, remove it - # update metadata (getUUID(object)) - # save new CNAFile - } + rCNA <- readRDS(file) + # remove sample if sample in `removedSamples` + newRCNA <- rCNA[, !(names(rCNA) %in% removedSamples)] + # update metadata - having issues, getting `invalid first argument` + # getUUID(newRCNA) + + # save new CNAFile with "filtered" prepended to filename + saveRDS(newRCNA, file = paste(dOut, "/filteredHypermutators_", basename(file), sep = "")) + } # for each rSNVFileIn for (file in rSNVFileIn) { - # for each sample (need to gsub("\.", "-", sample)), if hashTable$sample$total > xS, remove it - # update metadata (getUUID(object)) + rSNV <- readRDS(file) + + # for each sample (need to gsub("-", ".", sample)), if sample in `removedSamples` remove it + newRSNV <- rSNV[, !(gsub("-", ".", rSNV$Tumor_Sample_Barcode) %in% removedSamples)] + + # update metadata - having issues, getting `invalid first argument` + # getUUID(newRSNV) + # save new SNVFile + saveRDS(newRSNV, file = paste(dOut, "/filteredHypermutators_", basename(file), sep = "")) } ## LOGGING ############### diff --git a/tests/testthat/testFilter.R b/tests/testthat/testFilter.R index 868cbfb..70c6829 100644 --- a/tests/testthat/testFilter.R +++ b/tests/testthat/testFilter.R @@ -8,6 +8,12 @@ OLOG <- as.character(getOption("rete.logfile")) # save original logfile name logFileName(fPath = tempdir(), setOption = TRUE) # make tempdir() the log dir logName <- unlist(getOption("rete.logfile")) if (file.exists(logName)) { file.remove(logName)} + +SNVfileName <- '../../inst/extdata/devSNV.rds' +CNAfileName <- '../../inst/extdata/devCNA.rds' + +filteredSNVfileName <- paste(getwd(), "/filteredHypermutators_", basename(SNVfileName), sep = "") +filteredCNAfileName <- paste(getwd(), "/filteredHypermutators_", basename(CNAfileName), sep = "") # ==== END SETUP AND PREPARE =================================================== @@ -16,25 +22,28 @@ if (file.exists(logName)) { file.remove(logName)} # set up a tempdir and tempfiles for outputs of importFilterHypermutators test_that("importFilterHypermutators works correctly on valid input", { # run importFilterHypermutators on valid input - expect_error(importFilterHypermutators(rSNVFileIn = c('../../inst/extdata/devSNV.rds'), - rCNAFileIn = c('../../inst/extdata/devCNA.rds'), + expect_error(importFilterHypermutators(rSNVFileIn = c(SNVfileName), + rCNAFileIn = c(CNAfileName), dOut = getwd(), xS = 400, silent = FALSE, writeLog = TRUE), NA) + + if (file.exists(filteredSNVfileName)) { file.remove(filteredSNVfileName)} + if (file.exists(filteredCNAfileName)) { file.remove(filteredCNAfileName)} }) test_that("importFilterHypermutators rejects invalid dOut arguments", { # check for NULL object - expect_error(importFilterHypermutators(rSNVFileIn = c('../../inst/extdata/devSNV.rds'), - rCNAFileIn = c('../../inst/extdata/devCNA.rds'), + expect_error(importFilterHypermutators(rSNVFileIn = c(SNVfileName), + rCNAFileIn = c(CNAfileName), dOut = NULL, xS = 400, silent = FALSE, writeLog = TRUE)) # check for paths that don't exist - expect_error(importFilterHypermutators(rSNVFileIn = c('../../inst/extdata/devSNV.rds'), - rCNAFileIn = c('../../inst/extdata/devCNA.rds'), + expect_error(importFilterHypermutators(rSNVFileIn = c(SNVfileName), + rCNAFileIn = c(CNAfileName), dOut = 'no/such/path', xS = 400, silent = FALSE, @@ -43,14 +52,14 @@ test_that("importFilterHypermutators rejects invalid dOut arguments", { test_that("importFilterHypermutators rejects invalid xS arguments", { # check for including NULL objects - expect_error(importFilterHypermutators(rSNVFileIn = c('../../inst/extdata/devSNV.rds'), - rCNAFileIn = c('../../inst/extdata/devCNA.rds'), + expect_error(importFilterHypermutators(rSNVFileIn = c(SNVfileName), + rCNAFileIn = c(CNAfileName), xS = NULL, silent = FALSE, writeLog = TRUE)) # check character - expect_error(importFilterHypermutators(rSNVFileIn = c('../../inst/extdata/devSNV.rds'), - rCNAFileIn = c('../../inst/extdata/devCNA.rds'), + expect_error(importFilterHypermutators(rSNVFileIn = c(SNVfileName), + rCNAFileIn = c(CNAfileName), xS = "400", silent = FALSE, writeLog = TRUE)) @@ -58,14 +67,26 @@ test_that("importFilterHypermutators rejects invalid xS arguments", { test_that("importFilterHypermutators correctly removes hypermutators", { # run importFilterHypermutators with a single hypermutator + testCNA <- readRDS('../../inst/extdata/devCNA.rds') + testSNV <- readRDS('../../inst/extdata/devSNV.rds') + # check output file + readRDS('') + + # test cleanup + if (file.exists(filteredSNVfileName)) { file.remove(filteredSNVfileName)} + if (file.exists(filteredCNAfileName)) { file.remove(filteredCNAfileName)} }) # ==== BEGIN TEARDOWN AND RESTORE ============================================== logName <- unlist(getOption("rete.logfile")) if (file.exists(logName)) { file.remove(logName)} options("rete.logfile" = OLOG) + +# another check for function artifacts +if (file.exists(filteredSNVfileName)) { file.remove(filteredSNVfileName)} +if (file.exists(filteredCNAfileName)) { file.remove(filteredCNAfileName)} # ==== END TEARDOWN AND RESTORE =============================================== # [END] From dede433392af34347ff4322bdb47263934273eb1 Mon Sep 17 00:00:00 2001 From: Won June Tai Date: Thu, 30 Mar 2017 19:01:29 -0400 Subject: [PATCH 4/7] Ready for review --- R/importFilterHypermutators.R | 18 ++++++++------ man/importFilterHypermutators.Rd | 15 +++++++---- {inst/extdata => tests/testthat}/devCNA.rds | Bin {inst/extdata => tests/testthat}/devSNV.rds | Bin tests/testthat/testFilter.R | 26 ++++++++++++++++---- 5 files changed, 41 insertions(+), 18 deletions(-) rename {inst/extdata => tests/testthat}/devCNA.rds (100%) rename {inst/extdata => tests/testthat}/devSNV.rds (100%) diff --git a/R/importFilterHypermutators.R b/R/importFilterHypermutators.R index e961e66..30af486 100644 --- a/R/importFilterHypermutators.R +++ b/R/importFilterHypermutators.R @@ -66,10 +66,11 @@ importFilterHypermutators <- function(rSNVFileIn = c(), for (file in rCNAFileIn) { # readRDS, count gene CNAs and add to hash for sample @ CNA and nMUT rCNA <- readRDS(file) - for (sample in colnames(rCNA)) { + for (sample in colnames(rCNA)[4:length(colnames(rCNA))]) { totalSamples <- totalSamples + 1 # if key is in hash, increment CNA and nMUT for every gene if there is an abberation for (copyNumberValue in rCNA[[sample]]) { + copyNumberValue <- as.double(copyNumberValue) if (copyNumberValue != 0) { if (!is.null(hashTable[[sample]])) { prevCNACount <- hashTable[[sample]]$CNA @@ -102,7 +103,7 @@ importFilterHypermutators <- function(rSNVFileIn = c(), prevCNACount <- hashTable[[sample]]$CNA prevSNVCount <- hashTable[[sample]]$SNV prevTotalCount <- hashTable[[sample]]$total - assign(sample, list(CNA = prevCNACount, SNV = prevSNVCount + 1, nMUT = prevTotalCount + 1), envir = hashTable) + assign(sample, list(CNA = prevCNACount, SNV = prevSNVCount + 1, total = prevTotalCount + 1), envir = hashTable) } else { assign(sample, list(CNA = 0, SNV = 1, total = 1), envir = hashTable) } @@ -122,24 +123,24 @@ importFilterHypermutators <- function(rSNVFileIn = c(), for (sample in ls(hashTable)) { # num samples with only CNA - if (hashTable[[sample]]$SNV == 0) { + if (hashTable[[sample]]$SNV == 0 && hashTable[[sample]]$CNA > 0) { numSamplesOnlyCNA <- numSamplesOnlyCNA + 1 } # num samples with only SNV - else if (hashTable[[sample]]$CNA == 0) { + if (hashTable[[sample]]$CNA == 0 && hashTable[[sample]]$SNV > 0) { numSamplesOnlySNV <- numSamplesOnlySNV + 1 } # num samples with both SNV and CNA - else if (hashTable[[sample]]$CNA > 0 && hashTable[[sample]]$SNV > 0) { + if (hashTable[[sample]]$CNA > 0 && hashTable[[sample]]$SNV > 0) { numSamplesBothSNVAndCNA <- numSamplesBothSNVAndCNA + 1 } - # num samples that exceeded threshold and need removal - else if (hashTable[[sample]]$total > xS) { + # num samples that exceeded threshold and need to be removed + if (hashTable[[sample]]$total > xS) { numRemovedSamples <- numRemovedSamples + 1 removedSamples <- c(removedSamples, sample) } # num samples with no change - else { + if (hashTable[[sample]]$total <= xS) { numSamplesNoChange <- numSamplesNoChange + 1 } } @@ -149,6 +150,7 @@ importFilterHypermutators <- function(rSNVFileIn = c(), # for each rCNAFileIn for (file in rCNAFileIn) { rCNA <- readRDS(file) + # remove sample if sample in `removedSamples` newRCNA <- rCNA[, !(names(rCNA) %in% removedSamples)] diff --git a/man/importFilterHypermutators.Rd b/man/importFilterHypermutators.Rd index 87e7771..29e3a05 100644 --- a/man/importFilterHypermutators.Rd +++ b/man/importFilterHypermutators.Rd @@ -4,11 +4,14 @@ \alias{importFilterHypermutators} \title{Filters out hypermutators} \usage{ -importFilterHypermutators(fNames = c(), dOut = getwd(), xS = 400, - silent = FALSE, writeLog = TRUE) +importFilterHypermutators(rSNVFileIn = c(), rCNAFileIn = c(), + dOut = getwd(), xS = 400, silent = FALSE, writeLog = TRUE, + writeDetailedLog = TRUE) } \arguments{ -\item{fNames}{A vector of local file names of rMUT and/or rCNA files} +\item{rSNVFileIn}{A vector of local file names of rSNV} + +\item{rCNAFileIn}{A vector of local file names of rCNA} \item{dOut}{Directory to store output, defaults to getwd().} @@ -19,15 +22,17 @@ by default.} \item{writeLog}{Controls whether writing the result to the global logfile is enabled. TRUE by default.} + +\item{writeDetailedLog}{Flag for extra details about log. TRUE by default.} } \description{ \code{importFilterHypermutators} identifies the number of SNV and CNA -mutations for each sample and removes the samples from rMUT and rCNA +mutations for each sample and removes the samples from rSNV and rCNA datasets. Default threshold for removal is 400 mutations per sample. } \examples{ \dontrun{ - importFilterHypermutators(fNames, dOut, xS) + importFilterHypermutators(rSNVFileIn, rCNAFileIn, dOut, xS) } } diff --git a/inst/extdata/devCNA.rds b/tests/testthat/devCNA.rds similarity index 100% rename from inst/extdata/devCNA.rds rename to tests/testthat/devCNA.rds diff --git a/inst/extdata/devSNV.rds b/tests/testthat/devSNV.rds similarity index 100% rename from inst/extdata/devSNV.rds rename to tests/testthat/devSNV.rds diff --git a/tests/testthat/testFilter.R b/tests/testthat/testFilter.R index 70c6829..da625dc 100644 --- a/tests/testthat/testFilter.R +++ b/tests/testthat/testFilter.R @@ -9,8 +9,8 @@ logFileName(fPath = tempdir(), setOption = TRUE) # make tempdir() the log dir logName <- unlist(getOption("rete.logfile")) if (file.exists(logName)) { file.remove(logName)} -SNVfileName <- '../../inst/extdata/devSNV.rds' -CNAfileName <- '../../inst/extdata/devCNA.rds' +SNVfileName <- 'devSNV.rds' +CNAfileName <- 'devCNA.rds' filteredSNVfileName <- paste(getwd(), "/filteredHypermutators_", basename(SNVfileName), sep = "") filteredCNAfileName <- paste(getwd(), "/filteredHypermutators_", basename(CNAfileName), sep = "") @@ -67,12 +67,28 @@ test_that("importFilterHypermutators rejects invalid xS arguments", { test_that("importFilterHypermutators correctly removes hypermutators", { # run importFilterHypermutators with a single hypermutator - testCNA <- readRDS('../../inst/extdata/devCNA.rds') - testSNV <- readRDS('../../inst/extdata/devSNV.rds') + testCNA <- readRDS(CNAfileName) + testSNV <- readRDS(SNVfileName) + # start off with a known number of samples in each CNA and SNV file + expect_equal(length(colnames(testCNA)[4:length(colnames(testCNA))]), 579) + expect_equal(length(testSNV$Tumor_Sample_Barcode), 15) + + expect_error(importFilterHypermutators(rSNVFileIn = c(SNVfileName), + rCNAFileIn = c(CNAfileName), + xS = 15, + silent = FALSE, + writeLog = TRUE), NA) # check output file - readRDS('') + processedCNA <- readRDS(filteredCNAfileName) + processedSNV <- readRDS(filteredSNVfileName) + + # expect that 458 samples are removed from rCNA (579 - 458 = 121) + expect_equal(length(colnames(processedCNA)[4:length(colnames(processedCNA))]), 121) + + # expect that no samples are removed from rSNV + expect_equal(length(processedSNV$Tumor_Sample_Barcode), 15) # test cleanup if (file.exists(filteredSNVfileName)) { file.remove(filteredSNVfileName)} From 7a622cac5acfa55a5f4ab8d5451163eb532b53dd Mon Sep 17 00:00:00 2001 From: Won June Tai Date: Thu, 30 Mar 2017 19:58:00 -0400 Subject: [PATCH 5/7] Fixes getUUID arg --- R/importFilterHypermutators.R | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/R/importFilterHypermutators.R b/R/importFilterHypermutators.R index 30af486..1a3534c 100644 --- a/R/importFilterHypermutators.R +++ b/R/importFilterHypermutators.R @@ -155,7 +155,7 @@ importFilterHypermutators <- function(rSNVFileIn = c(), newRCNA <- rCNA[, !(names(rCNA) %in% removedSamples)] # update metadata - having issues, getting `invalid first argument` - # getUUID(newRCNA) + getUUID("newRCNA") # save new CNAFile with "filtered" prepended to filename saveRDS(newRCNA, file = paste(dOut, "/filteredHypermutators_", basename(file), sep = "")) @@ -169,7 +169,7 @@ importFilterHypermutators <- function(rSNVFileIn = c(), newRSNV <- rSNV[, !(gsub("-", ".", rSNV$Tumor_Sample_Barcode) %in% removedSamples)] # update metadata - having issues, getting `invalid first argument` - # getUUID(newRSNV) + getUUID("newRSNV") # save new SNVFile saveRDS(newRSNV, file = paste(dOut, "/filteredHypermutators_", basename(file), sep = "")) From ec91b67abddf5d2f604362fbb4d92df46ae3e436 Mon Sep 17 00:00:00 2001 From: Won June Tai Date: Thu, 30 Mar 2017 21:21:30 -0400 Subject: [PATCH 6/7] Addressing final comments --- R/importFilterHypermutators.R | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/R/importFilterHypermutators.R b/R/importFilterHypermutators.R index 1a3534c..8d5a8c5 100644 --- a/R/importFilterHypermutators.R +++ b/R/importFilterHypermutators.R @@ -154,7 +154,7 @@ importFilterHypermutators <- function(rSNVFileIn = c(), # remove sample if sample in `removedSamples` newRCNA <- rCNA[, !(names(rCNA) %in% removedSamples)] - # update metadata - having issues, getting `invalid first argument` + # update metadata getUUID("newRCNA") # save new CNAFile with "filtered" prepended to filename @@ -168,7 +168,7 @@ importFilterHypermutators <- function(rSNVFileIn = c(), # for each sample (need to gsub("-", ".", sample)), if sample in `removedSamples` remove it newRSNV <- rSNV[, !(gsub("-", ".", rSNV$Tumor_Sample_Barcode) %in% removedSamples)] - # update metadata - having issues, getting `invalid first argument` + # update metadata getUUID("newRSNV") # save new SNVFile @@ -184,8 +184,8 @@ importFilterHypermutators <- function(rSNVFileIn = c(), # Compile function call record logCall <- character() logCall[1] <- "importFilterHypermutators(" - logCall[2] <- sprintf("rSNVFileIn = \"%s\", ", rSNVFileIn) - logCall[3] <- sprintf("rCNAFileIn = \"%s\", ", rCNAFileIn) + logCall[2] <- sprintf("rSNVFileIn = (%s)", paste(rSNVFileIn, collapse(", "))) + logCall[3] <- sprintf("rCNAFileIn = (%s)", paste(rCNAFileIn, collapse(", "))) logCall[4] <- sprintf("dOut = \"%s\", ", dOut) logCall[5] <- sprintf("xS = \"%s\", ", as.character(xS)) logCall[6] <- sprintf("silent = %s, ", as.character(silent)) From 74d2436a1f3635f3cfd1e7c5886c743584f6347c Mon Sep 17 00:00:00 2001 From: Boris Steipe Date: Thu, 30 Mar 2017 21:48:54 -0400 Subject: [PATCH 7/7] added overwrite = TRUE to getUUID() calls. --- R/importFilterHypermutators.R | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/R/importFilterHypermutators.R b/R/importFilterHypermutators.R index 8d5a8c5..3a03399 100644 --- a/R/importFilterHypermutators.R +++ b/R/importFilterHypermutators.R @@ -155,7 +155,10 @@ importFilterHypermutators <- function(rSNVFileIn = c(), newRCNA <- rCNA[, !(names(rCNA) %in% removedSamples)] # update metadata - getUUID("newRCNA") + getUUID("newRCNA", overwrite = TRUE) + # ToDo: record updated UUID in log-file + # ToDo: test that UUID is _actually_ being updated. + # save new CNAFile with "filtered" prepended to filename saveRDS(newRCNA, file = paste(dOut, "/filteredHypermutators_", basename(file), sep = "")) @@ -169,7 +172,9 @@ importFilterHypermutators <- function(rSNVFileIn = c(), newRSNV <- rSNV[, !(gsub("-", ".", rSNV$Tumor_Sample_Barcode) %in% removedSamples)] # update metadata - getUUID("newRSNV") + getUUID("newRSNV", overwrite = TRUE) + # ToDo: record updated UUID in log-file + # ToDo: test that UUID is _actually_ being updated. # save new SNVFile saveRDS(newRSNV, file = paste(dOut, "/filteredHypermutators_", basename(file), sep = ""))