-
Notifications
You must be signed in to change notification settings - Fork 19
/
Copy pathsignature_obj_operation.R
137 lines (120 loc) · 4.02 KB
/
signature_obj_operation.R
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
#' Obtain or Modify Signature Information
#'
#' @param sig a `Signature` object obtained either from [sig_extract] or [sig_auto_extract].
#' @name sig_operation
#' @return a `Signature` object or data.
#' @export
#'
#' @examples
#' ## Operate signature names
#' load(system.file("extdata", "toy_mutational_signature.RData",
#' package = "sigminer", mustWork = TRUE
#' ))
#' sig_names(sig2)
#' cc <- sig_modify_names(sig2, new_names = c("Sig2", "Sig1", "Sig3"))
#' sig_names(cc)
#'
#' # The older names are stored in tags.
#' print(attr(cc, "tag"))
#' @testexamples
#' expect_is(cc, "Signature")
sig_names <- function(sig) {
stopifnot(inherits(sig, "Signature"))
colnames(sig$Signature)
}
#' @param new_names new signature names.
#' @rdname sig_operation
#' @export
sig_modify_names <- function(sig, new_names) {
ns <- sig_names(sig)
if (length(new_names) != length(ns)) {
stop("The new names should have same length as old names!")
}
colnames(sig$Signature) <- colnames(sig$Signature.norm) <- colnames(sig$Raw$W) <- rownames(sig$Exposure) <- rownames(sig$Exposure.norm) <- rownames(sig$Raw$H) <- new_names
attr(sig, "tag") <- paste0("Older names:", paste(ns, collapse = ","), ";")
sig
}
#' @rdname sig_operation
#' @export
#' @examples
#' ## Get signature number
#' sig_number(sig2)
sig_number <- function(sig) {
stopifnot(inherits(sig, "Signature"))
sig$K
}
#' @rdname sig_operation
#' @export
#' @examples
#' ## Get signature attributes
#' sig_number(sig2)
sig_attrs <- function(sig) {
stopifnot(inherits(sig, "Signature"))
attributes(sig)[!names(attributes(sig)) %in% c("names", "class")]
}
#' @param normalize one of 'row', 'column', 'raw' and "feature", for row normalization (signature),
#' column normalization (component), raw data, row normalization by feature, respectively.
#' @rdname sig_operation
#' @export
#' @examples
#' ## Get signature matrix
#' z <- sig_signature(sig2)
#' z <- sig_signature(sig2, normalize = "raw")
sig_signature <- function(sig, normalize = c("row", "column", "raw", "feature")) {
stopifnot(inherits(sig, "Signature"))
normalize <- match.arg(normalize)
sig <- sig$Signature
if (normalize == "row") {
sig <- apply(sig, 2, function(x) x / sum(x))
} else if (normalize == "column") {
sig <- t(apply(sig, 1, function(x) x / sum(x)))
} else if (normalize == "feature") {
has_cn <- grepl("^CN[^C]", rownames(sig)) | startsWith(rownames(sig), "copynumber")
if (!any(has_cn)) {
stop("normalize method 'feature' is only suitable for copy number signature!")
}
mat <- as.data.frame(sig)
mat$context <- rownames(mat)
if (any(grepl("^CN[^C]", rownames(sig)))) {
mat$base <- sub("\\[.*\\]$", "", mat$context)
} else {
mat$base <- sub("\\d+$", "", mat$context)
}
mat <- tidyr::gather(mat, class, signature, -c("context", "base"))
mat <- mat %>%
dplyr::group_by(.data$base, .data$class) %>%
tidyr::nest() %>%
dplyr::mutate(
context = purrr::map(.data$data, ~ .$context),
signature = purrr::map(.data$data, ~ .$signature / sum(.$signature))
) %>%
dplyr::select(-"data") %>%
tidyr::unnest(cols = c("context", "signature")) %>%
dplyr::ungroup()
mat <- tidyr::pivot_wider(mat, names_from = "class", values_from = "signature") %>%
dplyr::select(-"base") %>%
tibble::column_to_rownames("context") %>%
as.matrix()
# Keep row order same
sig <- mat[rownames(sig), ]
}
return(sig)
}
#' @param type one of 'absolute' and 'relative'.
#' @rdname sig_operation
#' @export
#' @examples
#' ## Get exposure matrix
#' ## Of note, this is different from get_sig_exposure()
#' ## it returns a matrix instead of data table.
#' z <- sig_exposure(sig2) # it is same as sig$Exposure
#' z <- sig_exposure(sig2, type = "relative") # it is same as sig2$Exposure.norm
sig_exposure <- function(sig, type = c("absolute", "relative")) {
stopifnot(inherits(sig, "Signature"))
type <- match.arg(type)
if (type == "absolute") {
return(sig$Exposure)
} else {
return(sig$Exposure.norm)
}
}