Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 31 additions & 3 deletions R/plots_featureimportance.R
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,29 @@ makeFeatureImportancePlot <- function(
}


#' Strip standalone "NA" tokens from a COG_name string
#'
#' The annotation source stores unnamed COG name slots as the literal string
#' "NA". Splits on `;` first so tokens adjacent to a semicolon get caught too.
#'
#' @param x Character vector of `COG_name` values.
#' @return Cleaned vector; `NA_character_` where no real name remains.
#' @keywords internal
#' @noRd
.clean_cog_name <- function(x) {
clean_one <- function(s) {
if (is.na(s)) return(NA_character_)
kept <- character(0)
for (p in trimws(strsplit(s, ";", fixed = TRUE)[[1]])) {
toks <- setdiff(strsplit(p, "[[:space:]]+")[[1]], c("NA", ""))
if (length(toks)) kept <- c(kept, paste(toks, collapse = " "))
}
if (!length(kept)) NA_character_ else paste(kept, collapse = "; ")
}
vapply(x, clean_one, character(1), USE.NAMES = FALSE)
}


#' Horizontal bar chart of the most common COGs
#'
#' Counts COG occurrences across the features in an annotation-enriched
Expand Down Expand Up @@ -314,9 +337,14 @@ makeCogBarChart <- function(enriched_tbl, top_n = 15) {

rows <- do.call(rbind, lapply(seq_len(nrow(cog_df)), function(i) {
cogs <- trimws(strsplit(cog_df$COG[i], ",", fixed = TRUE)[[1]])
names <- if ("COG_name" %in% names(cog_df) &&
!is.na(cog_df$COG_name[i])) {
n <- trimws(strsplit(cog_df$COG_name[i], ";", fixed = TRUE)[[1]])
# .clean_cog_name() strips "NA" placeholder tokens the source stuffs in.
clean <- if ("COG_name" %in% names(cog_df)) {
.clean_cog_name(cog_df$COG_name[i])
} else {
NA_character_
}
names <- if (!is.na(clean)) {
n <- trimws(strsplit(clean, ";", fixed = TRUE)[[1]])
rep_len(n, length(cogs))
} else {
rep(NA_character_, length(cogs))
Expand Down
34 changes: 34 additions & 0 deletions tests/testthat/test-makeCogBarChart.R
Original file line number Diff line number Diff line change
Expand Up @@ -60,3 +60,37 @@ test_that("makeCogBarChart respects top_n parameter", {
result <- makeCogBarChart(df, top_n = 5)
expect_s3_class(result, "plotly")
})

test_that(".clean_cog_name strips standalone NA tokens", {
expect_equal(.clean_cog_name("Alanine racemase NA NA NA"), "Alanine racemase")
expect_equal(
.clean_cog_name("D-serine deaminase NA"), "D-serine deaminase"
)
# NA tokens in the middle collapse too
expect_equal(.clean_cog_name("foo NA bar"), "foo bar")
})

test_that(".clean_cog_name returns NA when nothing meaningful remains", {
expect_true(is.na(.clean_cog_name("NA")))
expect_true(is.na(.clean_cog_name("NA NA NA")))
expect_true(is.na(.clean_cog_name(NA_character_)))
})

test_that(".clean_cog_name strips NA tokens adjacent to semicolons", {
expect_equal(
.clean_cog_name("Foo NA NA NA; Bar NA NA"),
"Foo; Bar"
)
expect_equal(
.clean_cog_name("Foo NA; NA; Bar"),
"Foo; Bar"
)
})

test_that(".clean_cog_name leaves clean names untouched and is vectorised", {
expect_equal(.clean_cog_name("Beta-lactamase class C"), "Beta-lactamase class C")
expect_equal(
.clean_cog_name(c("Helicase NA", "NA", "Transcription")),
c("Helicase", NA, "Transcription")
)
})