diff --git a/NAMESPACE b/NAMESPACE index 76467677..186ca517 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -5,8 +5,10 @@ export(IPG2Lineage) export(acc2FA) export(acc2Lineage) export(addLeaves2Alignment) +export(addLeaves2Alignment_legacy) export(addLineage) export(addName) +export(addName_lecacy) export(addTaxID) export(alignFasta) export(assignJobQueue) @@ -24,6 +26,7 @@ export(combineIPR) export(condenseRepeatedDomains) export(convert2TitleCase) export(convertAlignment2FA) +export(convertAlignment2FA_legacy) export(convertAlignment2Trees) export(convertFA2Tree) export(countByColumn) @@ -48,6 +51,7 @@ export(filterByFrequency) export(findParalogs) export(formatJobArgumentsHTML) export(generateAllAlignments2FA) +export(generateAllAlignments2FA_legacy) export(getAccNumFromFA) export(getProcessRuntimeWeights) export(getTopAccByLinDomArch) @@ -99,7 +103,9 @@ export(writeMSA_AA2FA) export(writeProcessRuntime2TSV) export(writeProcessRuntime2YML) importFrom(Biostrings,AAStringSet) +importFrom(Biostrings,readAAMultipleAlignment) importFrom(Biostrings,readAAStringSet) +importFrom(Biostrings,readDNAMultipleAlignment) importFrom(Biostrings,toString) importFrom(Biostrings,unmasked) importFrom(RColorBrewer,brewer.pal) diff --git a/R/CHANGED-pre-msa-tree.R b/R/CHANGED-pre-msa-tree.R index 62fcdc5c..e9e9aac7 100644 --- a/R/CHANGED-pre-msa-tree.R +++ b/R/CHANGED-pre-msa-tree.R @@ -73,7 +73,9 @@ convert2TitleCase <- function(x, y = " ") { #' Default is 'pspa.txt' #' @param reduced Boolean. If TRUE, a reduced data frame will be generated with #' only one sequence per lineage. Default is FALSE. +#' @param seq_type Character. Type of sequence, either "AA" or "DNA". Default is "AA". #' +#' @importFrom Biostrings readAAMultipleAlignment readDNAMultipleAlignment #' @importFrom dplyr distinct left_join mutate select #' @importFrom purrr map #' @importFrom readr read_file read_tsv @@ -99,7 +101,8 @@ convert2TitleCase <- function(x, y = " ") { addLeaves2Alignment <- function(aln_file = "", lin_file = "data/rawdata_tsv/all_semiclean.txt", # !! finally change to all_clean.txt!! # lin_file="data/rawdata_tsv/PspA.txt", - reduced = FALSE) { + reduced = FALSE, + seq_type = c("AA", "DNA")) { ## SAMPLE ARGS # aln_file <- "data/rawdata_aln/pspc.gismo.aln" # lin_file <- "data/rawdata_tsv/all_semiclean.txt" @@ -108,25 +111,36 @@ addLeaves2Alignment <- function(aln_file = "", # 1. Read aln & lineage master files files w/ read_file/read_tsv # 2. paste and collapse files so they can be read w/ tsv # 3. If the file has 1 column, separate it - aln <- read_file(aln_file) - lin <- read_tsv(lin_file) - aln <- paste(aln, sep = "\\s+", collapse = "\\t") - aln <- read_tsv(aln, col_names = F) - if (length(aln) == 1) { - colnames(aln) <- "x1" - aln <- separate(aln, - col = .data$x1, - into = c("x1", "x2"), - sep = "\\s+" - ) - } + seq_type <- match.arg(seq_type, c('AA', 'DNA')) + + # Read lineage data + lin <- read_tsv(lin_file, show_col_types = FALSE) - colnames(aln) <- c("AccNum", "Alignment") + # Detect file format + first_line <- readLines(aln_file, n = 1) + is_clustal <- grepl("^CLUSTAL", first_line, ignore.case = TRUE) + if (is_clustal) { + rlang::inform(rlang::format_error_bullets(c("i" = "Detected Clustal alignment: using Biostrings parser"))) + aln_obj <- switch( + seq_type, + AA = readAAMultipleAlignment(aln_file, format = "clustal"), + DNA = readDNAMultipleAlignment(aln_file, format = "clustal") + ) + + aln <- tibble( + AccNum = names(aln_obj), + Alignment = as.character(unmasked(aln_obj)) + ) + } else { + rlang::inform(rlang::format_error_bullets(c("i" = "Detected tabular alignment: reading with readr"))) + aln <- read_tsv(aln_file, col_names = c("AccNum", "Alignment"), show_col_types = FALSE) + } + aln_lin <- left_join(aln, lin, by = "AccNum") %>% select( - .data$AccNum, .data$Alignment, - .data$Species, .data$Lineage + 'AccNum', 'Alignment', + 'Species', 'Lineage' ) # Removes rows with NA @@ -178,7 +192,7 @@ addLeaves2Alignment <- function(aln_file = "", # Create Leaf_AccNum pasted together # 2 columns Leaf_AccNum and Sequence Far left leaf_aln <- temp %>% - select(.data$Leaf_Acc, .data$Alignment) + select('Leaf_Acc', 'Alignment') return(leaf_aln) } @@ -223,7 +237,9 @@ addName <- function(data, split_data <- data %>% separate( col = lin_col, into = c("Kingdom", "Phylum"), - sep = lin_sep + sep = lin_sep, + extra = 'drop', + fill = 'right' ) %>% mutate( Kingdom = strtrim(.data$Kingdom, 1), @@ -302,10 +318,30 @@ addName <- function(data, #' addLeaves2Alignment("pspa_snf7.aln", "pspa.txt") #' } #' +#' @importFrom data.table data.table convertAlignment2FA <- function(aln_file = "", lin_file = "data/rawdata_tsv/all_semiclean.txt", # !! finally change to all_clean.txt!! fa_outpath = "", reduced = FALSE) { + # Check if the alignment file is provided and exists + if (nchar(aln_file) == 0) { + abort("Error: Alignment file path must be provided.") + } + + if (!file.exists(aln_file)) { + abort(paste("Error: The alignment file '", aln_file, "' does not exist.")) + } + + # Check if the lineage file exists + if (!file.exists(lin_file)) { + abort(paste("Error: The lineage file '", lin_file, "' does not exist.")) + } + + # Check that the 'reduced' parameter is logical + if (!is.logical(reduced) || length(reduced) != 1) { + abort("Error: 'reduced' must be a single logical value (TRUE or FALSE).") + } + ## SAMPLE ARGS # aln_file <- "data/rawdata_aln/pspc.gismo.aln" # lin_file <- "data/rawdata_tsv/all_semiclean.txt" @@ -314,8 +350,8 @@ convertAlignment2FA <- function(aln_file = "", ## Add leaves aln <- addLeaves2Alignment( - aln = aln_file, - lin = lin_file, + aln_file = aln_file, + lin_file = lin_file, reduced = reduced ) names <- aln$Leaf_Acc @@ -451,12 +487,25 @@ renameFA <- function(fa_path, outpath, generateAllAlignments2FA <- function(aln_path = here("data/rawdata_aln/"), fa_outpath = here("data/alns/"), lin_file = here("data/rawdata_tsv/all_semiclean.txt"), - reduced = F) { - # library(here) - # library(tidyverse) - # aln_path <- here("data/rawdata_aln/") - # outpath <- here("data/alns/") - # lin_file <- here("data/rawdata_tsv/all_semiclean.txt") + reduced = FALSE) { + + if (!dir.exists(aln_path)) { + abort("Error: The alignment directory does not exist at the specified + path: ", aln_path) + } + + # Check if the output path exists; if not, attempt to create it + if (!dir.exists(fa_outpath)) { + dir.create(fa_outpath, recursive = TRUE) + message("Note: The output directory did not exist and has been created: ", + fa_outpath) + } + + # Check if the lineage file exists + if (!file.exists(lin_file)) { + abort("Error: The lineage file does not exist at the specified path: ", + lin_file) + } aln_filenames <- list.files(path = aln_path, pattern = "*.aln") aln_filepaths <- paste0(aln_path, "/", aln_filenames) @@ -726,7 +775,7 @@ writeMSA_AA2FA <- function(writeMSA_AA2FA, outpath) { #' } getAccNumFromFA <- function(fasta_file) { txt <- read_file(fasta_file) - accnums <- stringi::stri_extract_all_regex(fasta_file, "(?<=>)[\\w,.]+")[[1]] + accnums <- stringi::stri_extract_all_regex(txt, "(?<=>)[\\w,.]+")[[1]] return(accnums) } diff --git a/R/pre-msa-tree.R b/R/pre-msa-tree.R index 8cf3b8c3..3ad2478b 100644 --- a/R/pre-msa-tree.R +++ b/R/pre-msa-tree.R @@ -69,7 +69,7 @@ convert2TitleCase <- function(x, y = " ") { ################################ ## Function to add leaves to an alignment file ## !! Add DA to leaves? -#' addLeaves2Alignment +#' addLeaves2Alignment_legacy #' #' @author Janani Ravi #' @@ -109,7 +109,7 @@ convert2TitleCase <- function(x, y = " ") { #' \dontrun{ #' addLeaves2Alignment("pspa_snf7.aln", "pspa.txt") #' } -addLeaves2Alignment <- function(aln_file = "", +addLeaves2Alignment_legacy <- function(aln_file = "", lin_file = "data/rawdata_tsv/all_semiclean.txt", # !! finally change to all_clean.txt!! # lin_file="data/rawdata_tsv/PspA.txt", reduced = FALSE) { @@ -243,7 +243,7 @@ addLeaves2Alignment <- function(aln_file = "", #' \dontrun{ #' addName(data_frame) #' } -addName <- function(data, +addName_lecacy <- function(data, accnum_col = "AccNum", spec_col = "Species", lin_col = "Lineage", lin_sep = ">", out_col = "Name") { # Check if the data is a data fram @@ -341,7 +341,7 @@ addName <- function(data, #' \dontrun{ #' convertAlignment2FA("pspa_snf7.aln", "pspa.txt") #' } -convertAlignment2FA <- function(aln_file = "", +convertAlignment2FA_legacy <- function(aln_file = "", lin_file = "data/rawdata_tsv/all_semiclean.txt", # !! finally change to all_clean.txt!! fa_outpath = "", reduced = FALSE) { @@ -537,7 +537,7 @@ rename_fasta <- function(fa_path, outpath, #' \dontrun{ #' generateAllAlignments2FA() #' } -generateAllAlignments2FA <- function(aln_path = here("data/rawdata_aln/"), +generateAllAlignments2FA_legacy <- function(aln_path = here("data/rawdata_aln/"), fa_outpath = here("data/alns/"), lin_file = here("data/rawdata_tsv/all_semiclean.txt"), reduced = F) { @@ -554,9 +554,9 @@ generateAllAlignments2FA <- function(aln_path = here("data/rawdata_aln/"), fa_outpath) } - # Check if the linear file exists + # Check if the lineage file exists if (!file.exists(lin_file)) { - abort("Error: The linear file does not exist at the specified path: ", + abort("Error: The lineage file does not exist at the specified path: ", lin_file) } # library(here) diff --git a/man/addLeaves2Alignment.Rd b/man/addLeaves2Alignment.Rd index 85edc798..fa9849f3 100644 --- a/man/addLeaves2Alignment.Rd +++ b/man/addLeaves2Alignment.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/CHANGED-pre-msa-tree.R, R/pre-msa-tree.R +% Please edit documentation in R/CHANGED-pre-msa-tree.R \name{addLeaves2Alignment} \alias{addLeaves2Alignment} \title{addLeaves2Alignment} @@ -7,17 +7,12 @@ addLeaves2Alignment( aln_file = "", lin_file = "data/rawdata_tsv/all_semiclean.txt", - reduced = FALSE -) - -addLeaves2Alignment( - aln_file = "", - lin_file = "data/rawdata_tsv/all_semiclean.txt", - reduced = FALSE + reduced = FALSE, + seq_type = c("AA", "DNA") ) } \arguments{ -\item{aln_file}{Character. Path to file. Input tab-delimited file + +\item{aln_file}{haracter. Path to file. Input tab-delimited file + alignment file accnum & alignment. Default is 'pspa_snf7.aln'} @@ -27,34 +22,23 @@ Default is 'pspa.txt'} \item{reduced}{Boolean. If TRUE, a reduced data frame will be generated with only one sequence per lineage. Default is FALSE.} + +\item{seq_type}{Character. Type of sequence, either "AA" or "DNA". Default is "AA".} } \value{ A data frame containing the enriched alignment data with lineage information. - -A data frame containing the combined alignment and lineage -information. } \description{ -Adding Leaves to an alignment file w/ accessions -Genomic Contexts vs Domain Architectures. - Adding Leaves to an alignment file w/ accessions Genomic Contexts vs Domain Architectures. } \details{ -The alignment file would need two columns: 1. accession + -number and 2. alignment. The protein homolog accession to lineage mapping + -file should have - The alignment file would need two columns: 1. accession + number and 2. alignment. The protein homolog accession to lineage mapping + file should have } \note{ -Please refer to the source code if you have alternate + -file formats and/or column names. - Please refer to the source code if you have alternate + file formats and/or column names. } @@ -62,9 +46,6 @@ file formats and/or column names. \dontrun{ addLeaves2Alignment("pspa_snf7.aln", "pspa.txt") } -\dontrun{ -addLeaves2Alignment("pspa_snf7.aln", "pspa.txt") -} } \author{ Janani Ravi diff --git a/man/addLeaves2Alignment_legacy.Rd b/man/addLeaves2Alignment_legacy.Rd new file mode 100644 index 00000000..6e00e54b --- /dev/null +++ b/man/addLeaves2Alignment_legacy.Rd @@ -0,0 +1,54 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/pre-msa-tree.R +\name{addLeaves2Alignment_legacy} +\alias{addLeaves2Alignment_legacy} +\title{addLeaves2Alignment_legacy} +\usage{ +addLeaves2Alignment_legacy( + aln_file = "", + lin_file = "data/rawdata_tsv/all_semiclean.txt", + reduced = FALSE +) +} +\arguments{ +\item{aln_file}{Character. Path to file. Input tab-delimited file + +alignment file accnum & alignment. +Default is 'pspa_snf7.aln'} + +\item{lin_file}{Character. Path to file. Protein file with accession + +number to lineage mapping. +Default is 'pspa.txt'} + +\item{reduced}{Boolean. If TRUE, a reduced data frame will be generated with +only one sequence per lineage. Default is FALSE.} +} +\value{ +A data frame containing the combined alignment and lineage +information. +} +\description{ +Adding Leaves to an alignment file w/ accessions +Genomic Contexts vs Domain Architectures. +} +\details{ +The alignment file would need two columns: 1. accession + +number and 2. alignment. The protein homolog accession to lineage mapping + +file should have +} +\note{ +Please refer to the source code if you have alternate + +file formats and/or column names. +} +\examples{ +\dontrun{ +addLeaves2Alignment("pspa_snf7.aln", "pspa.txt") +} +} +\author{ +Janani Ravi +} +\keyword{accnum,} +\keyword{alignment,} +\keyword{leaves,} +\keyword{lineage,} +\keyword{species} diff --git a/man/addName.Rd b/man/addName.Rd index b681f349..e8d511a2 100644 --- a/man/addName.Rd +++ b/man/addName.Rd @@ -1,18 +1,9 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/CHANGED-pre-msa-tree.R, R/pre-msa-tree.R +% Please edit documentation in R/CHANGED-pre-msa-tree.R \name{addName} \alias{addName} \title{addName} \usage{ -addName( - data, - accnum_col = "AccNum", - spec_col = "Species", - lin_col = "Lineage", - lin_sep = ">", - out_col = "Name" -) - addName( data, accnum_col = "AccNum", @@ -37,16 +28,11 @@ addName( Lineage, and AccNum info} } \value{ -Original data with a 'Name' column - Original data with a 'Name' column } \description{ This function adds a new 'Name' column that is comprised of components from Kingdom, Phylum, Genus, and species, as well as the accession - -This function adds a new 'Name' column that is comprised of -components from Kingdom, Phylum, Genus, and species, as well as the accession } \examples{ # Example usage of the addName function @@ -57,9 +43,6 @@ data <- data.frame( ) enriched_data <- addName(data) enriched_data -\dontrun{ -addName(data_frame) -} } \author{ Samuel Chen, Janani Ravi diff --git a/man/addName_lecacy.Rd b/man/addName_lecacy.Rd new file mode 100644 index 00000000..6dfeee44 --- /dev/null +++ b/man/addName_lecacy.Rd @@ -0,0 +1,44 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/pre-msa-tree.R +\name{addName_lecacy} +\alias{addName_lecacy} +\title{addName} +\usage{ +addName_lecacy( + data, + accnum_col = "AccNum", + spec_col = "Species", + lin_col = "Lineage", + lin_sep = ">", + out_col = "Name" +) +} +\arguments{ +\item{data}{Data to add name column to} + +\item{accnum_col}{Column containing accession numbers} + +\item{spec_col}{Column containing species} + +\item{lin_col}{Column containing lineage} + +\item{lin_sep}{Character separating lineage levels} + +\item{out_col}{Column that contains the new 'Name' derived from Species, +Lineage, and AccNum info} +} +\value{ +Original data with a 'Name' column +} +\description{ +This function adds a new 'Name' column that is comprised of +components from Kingdom, Phylum, Genus, and species, as well as the accession +} +\examples{ +\dontrun{ +addName(data_frame) +} +} +\author{ +Samuel Chen, Janani Ravi +} diff --git a/man/convertAlignment2FA.Rd b/man/convertAlignment2FA.Rd index 528868c0..a776c943 100644 --- a/man/convertAlignment2FA.Rd +++ b/man/convertAlignment2FA.Rd @@ -1,16 +1,9 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/CHANGED-pre-msa-tree.R, R/pre-msa-tree.R +% Please edit documentation in R/CHANGED-pre-msa-tree.R \name{convertAlignment2FA} \alias{convertAlignment2FA} \title{convertAlignment2FA} \usage{ -convertAlignment2FA( - aln_file = "", - lin_file = "data/rawdata_tsv/all_semiclean.txt", - fa_outpath = "", - reduced = FALSE -) - convertAlignment2FA( aln_file = "", lin_file = "data/rawdata_tsv/all_semiclean.txt", @@ -30,35 +23,24 @@ Default is 'pspa.txt'} \item{fa_outpath}{Character. Path to the written fasta file. Default is 'NULL'} -\item{reduced}{Boolean. If TRUE, the fasta file will contain only one -sequence per lineage. Default is 'FALSE'} +\item{reduced}{Boolean. If TRUE, the fasta file will contain only one sequence per lineage. +Default is 'FALSE'} } \value{ A character string representing the FASTA formatted sequences. If \code{fa_outpath} is provided, the FASTA will also be saved to the specified file. - -Character string containing the Fasta formatted sequences. -If \code{fa_outpath} is specified, the function also writes the sequences to the -Fasta file. } \description{ Adding Leaves to an alignment file w/ accessions Genomic Contexts vs Domain Architectures. } \details{ -The alignment file would need two columns: 1. accession + -number and 2. alignment. The protein homolog accession to lineage mapping + -file should have - The alignment file would need two columns: 1. accession + number and 2. alignment. The protein homolog accession to lineage mapping + file should have } \note{ -Please refer to the source code if you have alternate + -file formats and/or column names. - Please refer to the source code if you have alternate + file formats and/or column names. } @@ -67,9 +49,6 @@ file formats and/or column names. addLeaves2Alignment("pspa_snf7.aln", "pspa.txt") } -\dontrun{ -convertAlignment2FA("pspa_snf7.aln", "pspa.txt") -} } \author{ Janani Ravi diff --git a/man/convertAlignment2FA_legacy.Rd b/man/convertAlignment2FA_legacy.Rd new file mode 100644 index 00000000..689a7071 --- /dev/null +++ b/man/convertAlignment2FA_legacy.Rd @@ -0,0 +1,58 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/pre-msa-tree.R +\name{convertAlignment2FA_legacy} +\alias{convertAlignment2FA_legacy} +\title{convertAlignment2FA} +\usage{ +convertAlignment2FA_legacy( + aln_file = "", + lin_file = "data/rawdata_tsv/all_semiclean.txt", + fa_outpath = "", + reduced = FALSE +) +} +\arguments{ +\item{aln_file}{Character. Path to file. Input tab-delimited file + +alignment file accnum & alignment. +Default is 'pspa_snf7.aln'} + +\item{lin_file}{Character. Path to file. Protein file with accession + +number to lineage mapping. +Default is 'pspa.txt'} + +\item{fa_outpath}{Character. Path to the written fasta file. +Default is 'NULL'} + +\item{reduced}{Boolean. If TRUE, the fasta file will contain only one +sequence per lineage. Default is 'FALSE'} +} +\value{ +Character string containing the Fasta formatted sequences. +If \code{fa_outpath} is specified, the function also writes the sequences to the +Fasta file. +} +\description{ +convertAlignment2FA +} +\details{ +The alignment file would need two columns: 1. accession + +number and 2. alignment. The protein homolog accession to lineage mapping + +file should have +} +\note{ +Please refer to the source code if you have alternate + +file formats and/or column names. +} +\examples{ +\dontrun{ +convertAlignment2FA("pspa_snf7.aln", "pspa.txt") +} +} +\author{ +Janani Ravi +} +\keyword{accnum,} +\keyword{alignment,} +\keyword{leaves,} +\keyword{lineage,} +\keyword{species} diff --git a/man/generateAllAlignments2FA.Rd b/man/generateAllAlignments2FA.Rd index 421d8cf7..8cc11e4e 100644 --- a/man/generateAllAlignments2FA.Rd +++ b/man/generateAllAlignments2FA.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/CHANGED-pre-msa-tree.R, R/pre-msa-tree.R +% Please edit documentation in R/CHANGED-pre-msa-tree.R \name{generateAllAlignments2FA} \alias{generateAllAlignments2FA} \title{generateAllAlignments2FA} @@ -8,14 +8,7 @@ generateAllAlignments2FA( aln_path = here("data/rawdata_aln/"), fa_outpath = here("data/alns/"), lin_file = here("data/rawdata_tsv/all_semiclean.txt"), - reduced = F -) - -generateAllAlignments2FA( - aln_path = here("data/rawdata_aln/"), - fa_outpath = here("data/alns/"), - lin_file = here("data/rawdata_tsv/all_semiclean.txt"), - reduced = F + reduced = FALSE ) } \arguments{ @@ -34,28 +27,15 @@ sequence per lineage. Default is 'FALSE'.} } \value{ -NULL. The function saves the output FASTA files to the specified -directory. - NULL. The function saves the output FASTA files to the specified directory. } \description{ Adding Leaves to an alignment file w/ accessions -Adding Leaves to all alignment files w/ accessions & DAs? - -Adding Leaves to an alignment file w/ accessions - Adding Leaves to all alignment files w/ accessions & DAs? } \details{ -The alignment files would need two columns separated by spaces: -\enumerate{ -\item AccNum and 2. alignment. The protein homolog file should have AccNum, -Species, Lineages. -} - The alignment files would need two columns separated by spaces: \enumerate{ \item AccNum and 2. alignment. The protein homolog file should have AccNum, @@ -63,9 +43,6 @@ Species, Lineages. } } \note{ -Please refer to the source code if you have alternate + file formats -and/or column names. - Please refer to the source code if you have alternate + file formats and/or column names. } @@ -73,9 +50,6 @@ and/or column names. \dontrun{ generateAllAlignments2FA() } -\dontrun{ -generateAllAlignments2FA() -} } \keyword{accnum,} \keyword{alignment,} diff --git a/man/generateAllAlignments2FA_legacy.Rd b/man/generateAllAlignments2FA_legacy.Rd new file mode 100644 index 00000000..c8d3df6e --- /dev/null +++ b/man/generateAllAlignments2FA_legacy.Rd @@ -0,0 +1,58 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/pre-msa-tree.R +\name{generateAllAlignments2FA_legacy} +\alias{generateAllAlignments2FA_legacy} +\title{generateAllAlignments2FA} +\usage{ +generateAllAlignments2FA_legacy( + aln_path = here("data/rawdata_aln/"), + fa_outpath = here("data/alns/"), + lin_file = here("data/rawdata_tsv/all_semiclean.txt"), + reduced = F +) +} +\arguments{ +\item{aln_path}{Character. Path to alignment files. +Default is 'here("data/rawdata_aln/")'} + +\item{fa_outpath}{Character. Path to file. Master protein file with AccNum & +lineages. +Default is 'here("data/rawdata_tsv/all_semiclean.txt")'} + +\item{lin_file}{Character. Path to the written fasta file. +Default is 'here("data/alns/")'.} + +\item{reduced}{Boolean. If TRUE, the fasta file will contain only one +sequence per lineage. +Default is 'FALSE'.} +} +\value{ +NULL. The function saves the output FASTA files to the specified +directory. +} +\description{ +Adding Leaves to an alignment file w/ accessions + +Adding Leaves to all alignment files w/ accessions & DAs? +} +\details{ +The alignment files would need two columns separated by spaces: +\enumerate{ +\item AccNum and 2. alignment. The protein homolog file should have AccNum, +Species, Lineages. +} +} +\note{ +Please refer to the source code if you have alternate + file formats +and/or column names. +} +\examples{ +\dontrun{ +generateAllAlignments2FA() +} +} +\keyword{accnum,} +\keyword{alignment,} +\keyword{leaves,} +\keyword{lineage,} +\keyword{species} diff --git a/tests/testthat/test-CHANGED-pre-msa-tree.R b/tests/testthat/test-CHANGED-pre-msa-tree.R new file mode 100644 index 00000000..1a466a80 --- /dev/null +++ b/tests/testthat/test-CHANGED-pre-msa-tree.R @@ -0,0 +1,525 @@ +context("CHANGED-test-pre-msa-tree") +test_that("CHANGED-test-pre-msa-tree", { + # Test with standard input + expect_equal(convert2TitleCase("hello world"), "Hello World") + expect_equal(convert2TitleCase("this is a test"), "This Is A Test") + + # Test with single word + expect_equal(convert2TitleCase("R"), "R") + expect_equal(convert2TitleCase("hello"), "Hello") + + # Test with punctuation + expect_equal(convert2TitleCase("capitalize every word."), + "Capitalize Every Word.") + expect_equal(convert2TitleCase("test, case, example"), + "Test, Case, Example") + + # Test with empty string + expect_equal(convert2TitleCase(""), "") + + # Test with multiple spaces + expect_equal(convert2TitleCase(" multiple spaces "), + " Multiple Spaces ") + + # Create mock alignment data + mock_alignment_data <- c( + "ACU53894.1\tMKTIIALSYI", + "APJ14606.1\tGSLKVSISY", + "ABK37082.1\tMKTLVAILA" + ) + + # Write the mock alignment data to a .aln file + aln_file <- file.path(tempdir(), "mock_alignment.aln") + writeLines(mock_alignment_data, aln_file) + + # Create mock lineage data + mock_lineage_data <- data.frame( + AccNum = c("ACU53894.1", "APJ14606.1", "ABK37082.1"), + Species = c("Species1", "Species2", "Species3"), + Lineage = c("Kingdom>Phylum1", "Kingdom>Phylum2", "Kingdom>Phylum3"), + stringsAsFactors = FALSE + ) + + # Write lineage data to a TSV file + lin_file <- file.path(tempdir(), "mock_lineage.tsv") + write_tsv(mock_lineage_data, lin_file) + + # Now you can test the function + result <- addLeaves2Alignment(aln_file, lin_file, seq_type = 'AA') + + # Check the structure of the result + expect_is(result, "data.frame") + + # Check the columns in the result + expect_true("Leaf_Acc" %in% colnames(result)) + expect_true("Alignment" %in% colnames(result)) + + # Check the content of the Leaf_Acc column + expect_equal(result$Leaf_Acc[1], "KPhylum_NASpe_ACU53894.1") + expect_equal(result$Leaf_Acc[2], "KPhylum_NASpe_APJ14606.1") + expect_equal(result$Leaf_Acc[3], "KPhylum_NASpe_ABK37082.1") + + # Check alignment sequences correspond to accession numbers + expect_equal(result$Alignment[1], "MKTIIALSYI") + expect_equal(result$Alignment[2], "GSLKVSISY") + expect_equal(result$Alignment[3], "MKTLVAILA") + + # Mock data to simulate input + mock_data <- tibble::tibble( + AccNum = c("Acc1", "Acc2", "Acc3", "Acc4"), + Species = c("Homo sapiens", "Escherichia coli", "Mus musculus", NA), + Lineage = c("Eukaryota>Chordata", "Bacteria>Proteobacteria", + "Eukaryota>Chordata", "Bacteria>Firmicutes") + ) + result <- addName(mock_data) + + # Check that the output contains the new Name column + expect_true("Name" %in% colnames(result)) + + # Check if the names are formatted correctly + expected_names <- c("EChorda_Hsapiens_Acc1", "BProteo_Ecoli_Acc2", + "EChorda_Mmusculus_Acc3", "BFirmic_Acc4") + expect_equal(result$Name, expected_names) + + # Test with NULL species column + result <- addName(mock_data, spec_col = NULL) + + # Check that species is ignored, and names are based on lineage and AccNum + expected_names <- c("EChorda_Acc1", "BProteo_Acc2", + "EChorda_Acc3", "BFirmic_Acc4") + expect_equal(result$Name, expected_names) + + # Create mock data with missing values + mock_data_with_missing <- tibble::tibble( + AccNum = c("Acc1", "Acc2", "Acc3"), + Species = c(NA, "Escherichia coli", NA), + Lineage = c(NA, "Bacteria>Proteobacteria", "Eukaryota>Chordata") + ) + + result <- addName(mock_data_with_missing) + + # Check that missing species and lineage data are handled correctly + expected_names <- c("_Acc1", "BProteo_Ecoli_Acc2", "EChorda_Acc3") + expect_equal(result$Name, expected_names) + + # Test with a different separator (e.g., "/") + mock_data_custom_sep <- mock_data + mock_data_custom_sep$Lineage <- gsub(">", "/", mock_data_custom_sep$Lineage) + + result <- addName(mock_data_custom_sep, lin_sep = "/") + + # Ensure the function correctly parses the lineage with the custom separator + expected_names <- c("EChorda_Hsapiens_Acc1", + "BProteo_Ecoli_Acc2", + "EChorda_Mmusculus_Acc3", + "BFirmic_Acc4") + expect_equal(result$Name, expected_names) + + # Test with an empty dataframe + empty_data <- tibble::tibble(AccNum = character(0), + Species = character(0), + Lineage = character(0)) + + result <- addName(empty_data) + + # Ensure the result is still a dataframe with the expected structure + expect_equal(nrow(result), 0) + expect_true("Name" %in% colnames(result)) + + # Create mock data that might result in extra underscores + mock_data_with_gaps <- tibble::tibble( + AccNum = c("Acc1", "Acc2"), + Species = c(NA, "Escherichia coli"), + Lineage = c("Eukaryota", "Bacteria>Proteobacteria") + ) + + result <- addName(mock_data_with_gaps) + + # Ensure no extra underscores are present in the Name column + expected_names <- c("E_Acc1", "BProteo_Ecoli_Acc2") + expect_equal(result$Name, expected_names) + + + + + # Call the function to convert alignment to FASTA + result <- convertAlignment2FA( + aln_file = aln_file, + lin_file = lin_file, + fa_outpath = NULL, + reduced = FALSE + ) + + # Expected FASTA format output + expected_fasta <- ">KPhylum_NASpe_ACU53894.1\nMKTIIALSYI\n>KPhylum_NASpe_APJ14606.1\nGSLKVSISY\n>KPhylum_NASpe_ABK37082.1\nMKTLVAILA\n" + + # Check if the result matches the expected FASTA output + expect_equal(result, expected_fasta) + + # Temporary output file path + fa_outpath <- tempfile(fileext = ".fasta") + + # Call the function to convert alignment to FASTA and save it to a file + convertAlignment2FA( + aln_file = aln_file, + lin_file = lin_file, + fa_outpath = fa_outpath, + reduced = FALSE + ) + + # Read the generated FASTA file + fasta_content <- read_file(fa_outpath) + + # Expected FASTA format output + expected_fasta <- ">KPhylum_NASpe_ACU53894.1\nMKTIIALSYI\n>KPhylum_NASpe_APJ14606.1\nGSLKVSISY\n>KPhylum_NASpe_ABK37082.1\nMKTLVAILA\n" + + # Check if the generated file content matches the expected FASTA output + expect_equal(fasta_content, expected_fasta) + + # Call the function with reduced mode enabled + result <- convertAlignment2FA( + aln_file = aln_file, + lin_file = lin_file, + fa_outpath = NULL, + reduced = TRUE + ) + + # In reduced mode, we expect one sequence per unique lineage + expected_fasta <- ">KPhylum_NASpe_ACU53894.1\nMKTIIALSYI\n>KPhylum_NASpe_APJ14606.1\nGSLKVSISY\n>KPhylum_NASpe_ABK37082.1\nMKTLVAILA\n" + + # Check if the result matches the expected FASTA output with + # reduced sequences + expect_equal(result, expected_fasta) + + # Clean up mock files after test + file.remove(aln_file) + file.remove(lin_file) + + # Mock data for acc2name + acc2name <- tibble::tibble( + AccNum = c("Acc1", "Acc2", "Acc3", "Acc4"), + Name = c("Name1", "Name2", "Name3", "Name4") + ) + + # Sample FASTA line with Acc1 + line <- ">Acc1 AAAATTTTCCCCGGGG" + + # Call the function + result <- mapAcc2Name(line, acc2name) + + # Expected output + expected <- ">Name1" + + # Check if the result matches the expected output + expect_equal(result, expected) + + # Sample FASTA line with an unknown accession number + line <- ">Acc5 TTTTCCCCGGGGAAAA" + + # Call the function + result <- mapAcc2Name(line, acc2name) + + # Expected output (no match found) + expected <- ">NA" + + # Check if the result matches the expected output + expect_equal(result, expected) + + # Empty line + line <- "" + + # Call the function + result <- mapAcc2Name(line, acc2name) + + # Expected output (should return an empty or NA-like result) + expect_equal(result, ">NA") + + # Sample FASTA line with extra spaces + line <- ">Acc2 TTTTCCCCGGGGAAAA" + + # Call the function + result <- mapAcc2Name(line, acc2name) + + # Expected output + expected <- ">Name2" + + # Check if the result matches the expected output + expect_equal(result, expected) + + # Sample FASTA line with a lowercase accession number + # Acc1 is in lowercase, but acc2name has uppercase + line <- ">acc1 AAAATTTTCCCCGGGG" + + # Call the function + result <- mapAcc2Name(line, acc2name) + + # Expected output: should not find the accession number + # because of case difference + expected <- ">NA" + + # Check if the result matches the expected output + expect_equal(result, expected) + + # Mock data for acc2name + acc2name <- tibble::tibble( + AccNum = c("Acc1", "Acc2", "Acc3"), + Name = c("Name1", "Name2", "Name3") + ) + + # Mock FASTA file lines + mock_fasta <- c( + ">Acc1 description", + "AAAATTTTCCCCGGGG", + ">Acc2 description", + "GGGGTTTTAAAACCCC", + ">Acc3 description", + "CCCCAAAAGGGGTTTT" + ) + + # Create a temporary file for the mock FASTA file + fa_path <- tempfile(fileext = ".fa") + writeLines(mock_fasta, fa_path) + + # Output file path + outpath <- tempfile(fileext = ".fa") + + # Call the renameFA function + result <- renameFA(fa_path, outpath, + replacement_function = mapAcc2Name, + acc2name = acc2name) + + # Expected result after renaming + expected <- c( + ">Name1", + "AAAATTTTCCCCGGGG", + ">Name2", + "GGGGTTTTAAAACCCC", + ">Name3", + "CCCCAAAAGGGGTTTT" + ) + + # Check if the result matches the expected output + expect_equal(result, expected) + + # Call the renameFA function + result <- renameFA(fa_path, outpath, + replacement_function = mapAcc2Name, + acc2name = acc2name) + + # Extract the sequence lines (should not change) + sequence_lines <- result[c(2, 4, 6)] + expected_sequences <- c("AAAATTTTCCCCGGGG", + "GGGGTTTTAAAACCCC", + "CCCCAAAAGGGGTTTT") + + # Check if sequence lines match the original content + expect_equal(sequence_lines, expected_sequences) + + # Custom function that just appends '_custom' to the accession number + custom_replacement <- function(line, ...) { + acc <- str_sub(line, 2) # Remove '>' + return(paste0(">", acc, "_custom")) + } + + # Call the renameFA function with the custom function + result <- renameFA(fa_path, outpath, + replacement_function = custom_replacement) + + # Expected result after renaming with the custom function + expected <- c( + ">Acc1 description_custom", + "AAAATTTTCCCCGGGG", + ">Acc2 description_custom", + "GGGGTTTTAAAACCCC", + ">Acc3 description_custom", + "CCCCAAAAGGGGTTTT" + ) + + # Check if the result matches the expected output + expect_equal(result, expected) + + # Create an empty file + empty_fa <- tempfile(fileext = ".fa") + writeLines(character(0), empty_fa) + + # Call the renameFA function with the empty file + result <- renameFA(empty_fa, outpath, + replacement_function = mapAcc2Name, + acc2name = acc2name) + + # Expected output is an empty character vector + expect_equal(result, NULL) + + # Call the renameFA function with multiple sequences + result <- renameFA(fa_path, outpath, + replacement_function = mapAcc2Name, + acc2name = acc2name) + + # Expected result + expected <- c( + ">Name1", + "AAAATTTTCCCCGGGG", + ">Name2", + "GGGGTTTTAAAACCCC", + ">Name3", + "CCCCAAAAGGGGTTTT" + ) + + # Check if the result matches the expected output + expect_equal(result, expected) + + # Setup: Create a temporary directory for alignment files + aln_dir <- tempdir() + fa_dir <- tempdir() + lin_dir <- tempdir() + + # Create tabular alignment files (two columns: AccNum Alignment) + aln1 <- + tibble::tibble( + AccNum = c("Acc1", "Acc2"), + Alignment = c("ATGCNNNN", "ATGCNNNN") + ) + + aln2 <- + tibble::tibble( + AccNum = c("Acc3", "Acc4"), + Alignment = c("ATGCNNNN", "ATGCNNNN") + ) + + # Write without column names so read_tsv(..., col_names = c("AccNum","Alignment")) works + readr::write_tsv(aln1, file.path(aln_dir, "test1.aln"), col_names = FALSE) + readr::write_tsv(aln2, file.path(aln_dir, "test2.aln"), col_names = FALSE) + + # Create mock lineage data (AccNum, Species, Lineage) + mock_lineage_data <- tibble::tibble( + AccNum = c("Acc1", "Acc2", "Acc3", "Acc4"), + Species = c("Species A", "Species B", "Species C", "Species D"), + Lineage = c("Kingdom>Phylum1", "Kingdom>Phylum1", + "Kingdom>Phylum2", "Kingdom>Phylum2") + ) + + # Save the mock lineage data as a TSV file + write_tsv(mock_lineage_data, file.path(lin_dir, "all_semiclean.txt")) + + # Call the function + generateAllAlignments2FA(aln_path = aln_dir, + fa_outpath = fa_dir, + lin_file = file.path(lin_dir, "all_semiclean.txt")) + + # Check if output files are created + output_files <- list.files(fa_dir, pattern = "*.fa", full.names = TRUE) + expect_true(length(output_files) > 0) + + # Create a temporary empty directory and test for error handling + empty_dir <- tempdir() + fa_dir <- tempdir() + + # Setup: Create a temporary directory for alignment files + aln_dir <- tempdir() + fa_dir <- tempdir() + + # Create mock alignment data as a tibble + mock_aln <- tibble( + AccNum = c("Acc1", "Acc2"), + Alignment = c("ATGCNNNN", "ATGCNNNN") + ) + + # Write as a tab-delimited file without header row + # (so read_tsv(..., col_names = c("AccNum","Alignment")) will work correctly) + write_tsv(mock_aln, + file = file.path(aln_dir, "test1.aln"), + col_names = FALSE) + # # Create mock alignment files + # writeLines(c(">Acc1\nATGCNNNN\n>Acc2\nATGCNNNN\n"), + # file.path(aln_dir, "test1.aln")) + + # Create mock lineage data + mock_lineage_data <- tibble::tibble( + AccNum = c("Acc1", "Acc2"), + Species = c("Species A", "Species B"), + Lineage = c("Kingdom>Phylum1", "Kingdom>Phylum1") + ) + + # Save the mock lineage data as a TSV file + write_tsv(mock_lineage_data, file.path(lin_dir, "all_semiclean.txt")) + + # Call the function with reduced = TRUE + generateAllAlignments2FA(aln_path = aln_dir, + fa_outpath = fa_dir, + lin_file = file.path(lin_dir, "all_semiclean.txt"), + reduced = TRUE) + + # Check if output files are created + output_files <- list.files(fa_dir, pattern = "*.fa", full.names = TRUE) + expect_true(length(output_files) > 0) + + # Check the content of the output file + fasta_content <- readLines(outpath) + expect_equal(fasta_content[1], ">Name1") + + # Sample Data for Testing + prot_data <- tibble::tibble( + AccNum = c("A001", "A002", "A003", "A004", "A005"), + Lineage = c("L1", "L1", "L2", "L2", NA) + ) + + result <- createRepresentativeAccNum(prot_data, reduced = "Lineage", accnum_col = "AccNum") + + expect_equal(result, c("A001", "A003")) # A001 for L1 and A003 for L2 + + result <- createRepresentativeAccNum(prot_data, reduced = "Lineage", accnum_col = "AccNum") + + expect_false(any(is.na(result))) # No NA values in result + expect_equal(length(result), 2) # Still only 2 unique Lineages + + prot_data_with_duplicates <- tibble::tibble( + AccNum = c("A001", "A001", "A002", "A003", "A004", "A004"), + Lineage = c("L1", "L1", "L2", "L2", "L3", "L3") + ) + + result <- createRepresentativeAccNum(prot_data_with_duplicates, + reduced = "Lineage", accnum_col = "AccNum") + + # A001 for L1, A002 for L2, and one for L3 + expect_equal(result, c("A001", "A002", "A004")) + + empty_data <- tibble::tibble(AccNum = character(), Lineage = character()) + + result <- createRepresentativeAccNum(empty_data, + reduced = "Lineage", + accnum_col = "AccNum") + + expect_equal(result, NULL) # Expecting an empty character vector + + # Create a mock FASTA file for testing + create_mock_fasta <- function(file_path) { + seqs <- c(">seq1\nACGT\n>seq2\nACGT\n>seq3\nACGT") + writeLines(seqs, con = file_path) + } + + # Path for the mock FASTA file + mock_fasta_path <- "mock_sequences.fasta" + create_mock_fasta(mock_fasta_path) + + aligned <- alignFasta(mock_fasta_path, tool = "Muscle") + + # Check the class of the returned object + expect_s4_class(aligned, "MsaAAMultipleAlignment") + + aligned <- alignFasta(mock_fasta_path, tool = "ClustalO") + + # Check the class of the returned object + expect_s4_class(aligned, "MsaAAMultipleAlignment") + + aligned <- alignFasta(mock_fasta_path, tool = "ClustalW") + + # Check the class of the returned object + expect_s4_class(aligned, "MsaAAMultipleAlignment") + + # Expect error for non-existing file + expect_error(alignFasta("non_existing_file.fasta", tool = "Muscle"), + "Error: The FASTA file does not exist: ") + + # Clean up mock fasta file after tests + file.remove(mock_fasta_path) +})