Skip to content

Commit 038dd5d

Browse files
authored
fix(turnover): Fix DIANN 1.8 processing of protein turnover labeling (#140)
1 parent dbf8afb commit 038dd5d

8 files changed

Lines changed: 105 additions & 34 deletions

R/clean_DIANN.R

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -231,12 +231,17 @@
231231
#' \strong{not} used to validate or filter \code{ModifiedSequence}.
232232
#'
233233
#' \strong{ModifiedSequence-parsing path} (\code{has_channel = FALSE}):
234-
#' \code{PeptideSequence} (the retained \code{ModifiedSequence}) is matched
235-
#' against SILAC suffixes of the form \code{(SILAC-<AA>-H)} or
236-
#' \code{(SILAC-<AA>-L)}, where \code{<AA>} is any code in
237-
#' \code{labeledAminoAcids}. Sequences carrying neither suffix receive
238-
#' \code{IsotopeLabelType = NA}. The SILAC suffix is stripped from
239-
#' \code{PeptideSequence} after classification.
234+
#' \code{PeptideSequence} (the retained \code{ModifiedSequence}) is scanned
235+
#' for isotope-labeled amino acids, which appear in parentheses immediately
236+
#' after the labeled residue, in the form \code{(<label>-<aminoAcid>-H)} for
237+
#' the heavy label or \code{(<label>-<aminoAcid>-L)} for the light label.
238+
#' For example, \code{K(label-K-H)} marks a heavy-labeled lysine (\code{K}).
239+
#' Here \code{<aminoAcid>} is one of the single-letter codes in
240+
#' \code{labeledAminoAcids}, and \code{<label>} is the label name (e.g.
241+
#' \code{SILAC} or \code{label}). Sequences with no such parenthetical
242+
#' tags are assigned \code{IsotopeLabelType = NA}. Once classified, the
243+
#' parenthetical annotation is stripped out of \code{PeptideSequence},
244+
#' leaving the plain amino acid sequence.
240245
#'
241246
#' @param dn_input \code{data.table} after column renaming.
242247
#' @param labeledAminoAcids Character vector of single-letter amino acid codes
@@ -265,9 +270,9 @@
265270
dn_input[, Channel := NULL]
266271
} else {
267272
aa_pattern <- paste0(labeledAminoAcids, collapse = "|")
268-
heavy_regex <- paste0("\\(SILAC-(?:", aa_pattern, ")-H\\)")
269-
light_regex <- paste0("\\(SILAC-(?:", aa_pattern, ")-L\\)")
270-
strip_regex <- paste0("\\(SILAC-(?:", aa_pattern, ")-[HL]\\)")
273+
heavy_regex <- paste0("\\([^-]+-(?:", aa_pattern, ")-H\\)")
274+
light_regex <- paste0("\\([^-]+-(?:", aa_pattern, ")-L\\)")
275+
strip_regex <- paste0("\\([^-]+-(?:", aa_pattern, ")-[HL]\\)")
271276

272277
dn_input <- .classifyIsotopeLabelType(dn_input, heavy_regex, light_regex)
273278
dn_input[, PeptideSequence := gsub(strip_regex, "", PeptideSequence, perl = TRUE)]
@@ -276,7 +281,9 @@
276281
if (all(is.na(dn_input[["IsotopeLabelType"]]))) {
277282
warning("labeledAminoAcids was provided but no rows were classified as H or L. ",
278283
"Check that the input contains either a Channel column with H/L values ",
279-
"or ModifiedSequence entries with (SILAC-<AA>-H)/(SILAC-<AA>-L) suffixes.")
284+
"or ModifiedSequence entries with isotope-labeled amino acids",
285+
"which appear in parentheses immediately after the labeled residue",
286+
"e.g. (SILAC-K-H).")
280287
}
281288

282289
dn_input

R/clean_ProteinProspector.R

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
#' @param msstats_object object that inherits from MSstatsInputFiles class.
33
#' @return data.table
44
#' @keywords internal
5-
#' @noRd
65
.cleanRawProteinProspector = function(msstats_object) {
76
PSM = PeptideSequence = PrecursorCharge = NULL
87
protein_prospector_input = getInputFile(msstats_object, "input")

R/converters_DIANNtoMSstatsFormat.R

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -35,12 +35,18 @@
3535
#'
3636
#' \strong{ModifiedSequence-parsing path} (DIA-NN 1.x exports without a
3737
#' \code{Channel} column): when \code{labeledAminoAcids} is non-\code{NULL}
38-
#' and no \code{Channel} column is present, each \code{ModifiedSequence} is
39-
#' inspected for SILAC suffixes of the form \code{(SILAC-<AA>-H)} or
40-
#' \code{(SILAC-<AA>-L)}, where \code{<AA>} is one of the supplied amino acid
41-
#' codes. Matching sequences are classified as \code{"H"} or \code{"L"};
42-
#' sequences carrying neither suffix receive \code{IsotopeLabelType = NA}.
43-
#' The SILAC suffix is then stripped from \code{PeptideSequence}.
38+
#' and no \code{Channel} column is present, each \code{ModifiedSequence} is
39+
#' scanned for isotope-labeled amino acids, which appear in parentheses
40+
#' immediately after the labeled residue,
41+
#' in the form \code{(<label>-<aminoAcid>-H)} for
42+
#' the heavy label or \code{(<label>-<aminoAcid>-L)} for the light label.
43+
#' For example, \code{K(label-K-H)} marks a heavy-labeled lysine (\code{K}).
44+
#' Here \code{<aminoAcid>} is one of the single-letter codes in
45+
#' \code{labeledAminoAcids}, and \code{<label>} is the label name (e.g.
46+
#' \code{SILAC} or \code{label}). Sequences with no such parenthetical
47+
#' tags are assigned \code{IsotopeLabelType = NA}. Once classified, the
48+
#' parenthetical annotation is stripped out of \code{PeptideSequence},
49+
#' leaving the plain amino acid sequence.
4450
#'
4551
#' When \code{NULL} (default), protein-turnover mode is disabled and all
4652
#' peptides receive \code{IsotopeLabelType = "Light"}.

inst/tinytest/test_clean_DIANN.R

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ output <- MSstatsConvert:::.cleanRawDIANN(input, MBR = FALSE, pg_qvalue_cutoff =
5656
expect_qvalue_cutoff(output, "GlobalPGQValue", 0.0002)
5757

5858
# Test .assignDIANNIsotopeLabelType ---------------------------
59-
# Channel path: Channel column is mapped to IsotopeLabelType, then dropped
59+
6060
dt_channel = data.table::data.table(
6161
PeptideSequence = c("PEPTIDEK", "PEPTIDEK", "PEPTIDEK"),
6262
Channel = c("H", "L", "other")
@@ -67,7 +67,6 @@ result_channel = MSstatsConvert:::.assignDIANNIsotopeLabelType(
6767
expect_equal(result_channel$IsotopeLabelType, c("H", "L", NA_character_))
6868
expect_false("Channel" %in% colnames(result_channel))
6969

70-
# NULL path: labeledAminoAcids = NULL returns input unchanged (no IsotopeLabelType added)
7170
dt_null = data.table::data.table(
7271
PeptideSequence = c("PEPTIDEK(SILAC-K-H)", "PEPTIDEK(SILAC-K-L)")
7372
)
@@ -76,3 +75,27 @@ result_null = MSstatsConvert:::.assignDIANNIsotopeLabelType(
7675
)
7776
expect_false("IsotopeLabelType" %in% colnames(result_null))
7877
expect_equal(nrow(result_null), 2L)
78+
79+
dt_label = data.table::data.table(
80+
PeptideSequence = c("PEPTIDEK(SILAC-K-H)", "PEPTIDEK(SILAC-K-L)",
81+
"PEPTIDEK(label-K-H)", "PEPTIDEK(label-K-L)",
82+
"PEPTIDEK")
83+
)
84+
result_label = MSstatsConvert:::.assignDIANNIsotopeLabelType(
85+
dt_label, labeledAminoAcids = c("K"), has_channel = FALSE
86+
)
87+
expect_equal(result_label$IsotopeLabelType, c("H", "L", "H", "L", NA_character_))
88+
expect_equal(unique(result_label$PeptideSequence), "PEPTIDEK")
89+
90+
dt_multi_aa = data.table::data.table(
91+
PeptideSequence = c("PEPTIDEK(SILAC-K-H)", "PEPTIDER(SILAC-R-H)",
92+
"PEPTIDEK(SILAC-K-L)", "PEPTIDER(SILAC-R-L)",
93+
"PEPTIDEAC")
94+
)
95+
result_multi_aa = MSstatsConvert:::.assignDIANNIsotopeLabelType(
96+
dt_multi_aa, labeledAminoAcids = c("K", "R"), has_channel = FALSE
97+
)
98+
expect_equal(result_multi_aa$IsotopeLabelType,
99+
c("H", "H", "L", "L", NA_character_))
100+
expect_equal(sort(unique(result_multi_aa$PeptideSequence)),
101+
c("PEPTIDEAC", "PEPTIDEK", "PEPTIDER"))

man/DIANNtoMSstatsFormat.Rd

Lines changed: 11 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

man/MSstatsClean.Rd

Lines changed: 11 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

man/dot-cleanRawDIANN.Rd

Lines changed: 11 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

man/dot-cleanRawProteinProspector.Rd

Lines changed: 18 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)