|
17 | 17 | #' @keywords internal |
18 | 18 | .cleanRawMZMine <- function(msstats_object, mzmine_annotations = NULL) { |
19 | 19 | ProteinName = PeptideSequence = Intensity = Run = NULL |
20 | | - PrecursorCharge = FragmentIon = ProductCharge = IsotopeLabelType = NULL |
21 | | - sample_col = id = score = compound_name = NULL |
| 20 | + PrecursorCharge = FragmentIon = ProductCharge = NULL |
| 21 | + id = score = compound_name = i.compound_name = NULL |
22 | 22 |
|
23 | 23 | mz_input <- getInputFile(msstats_object, "input") |
24 | 24 | mz_input <- data.table::as.data.table(mz_input) |
|
43 | 43 |
|
44 | 44 | mz_rt_fallback <- paste0(round(mz_input[[mz_col]], 4), "_", |
45 | 45 | round(mz_input[[rt_col]], 2)) |
| 46 | + mz_input[, ProteinName := mz_rt_fallback] |
46 | 47 |
|
47 | 48 | if (!is.null(mzmine_annotations)) { |
48 | | - ann <- data.table::as.data.table(mzmine_annotations) |
| 49 | + feature_to_compound <- data.table::as.data.table(mzmine_annotations) |
49 | 50 | required_ann <- c("id", "compound_name", "score") |
50 | | - missing_ann <- setdiff(required_ann, colnames(ann)) |
| 51 | + missing_ann <- setdiff(required_ann, colnames(feature_to_compound)) |
51 | 52 | if (length(missing_ann) > 0) { |
52 | 53 | stop("mzmine_annotations is missing required column(s): ", |
53 | 54 | paste(missing_ann, collapse = ", "), ".") |
54 | 55 | } |
55 | | - ann[, score := suppressWarnings(as.numeric(as.character(score)))] |
56 | | - if (anyNA(ann$score)) { |
57 | | - stop("mzmine_annotations$score must be numeric (or coercible to numeric).") |
| 56 | + feature_to_compound[, score := suppressWarnings(as.numeric(score))] |
| 57 | + if (anyNA(feature_to_compound$score)) { |
| 58 | + stop("The 'score' column in the mzmine annotations file must contain numeric values.") |
58 | 59 | } |
59 | | - data.table::setorder(ann, id, -score) |
60 | | - ann_top <- unique(ann, by = "id") |
61 | | - matched <- ann_top[match(mz_input[[id_col]], ann_top[["id"]]), |
62 | | - compound_name] |
63 | | - compound <- ifelse(is.na(matched), mz_rt_fallback, matched) |
64 | | - } else { |
65 | | - compound <- mz_rt_fallback |
| 60 | + # Sort by id ascending and score descending so the highest-scoring |
| 61 | + # annotation per id is the first row in each group. |
| 62 | + data.table::setorder(feature_to_compound, id, -score) |
| 63 | + # Collapse to one row per id (the highest-scoring). data.table's |
| 64 | + # unique() with a 'by' arg keeps the first row per group, which after |
| 65 | + # the sort above is the highest-scoring annotation. |
| 66 | + feature_to_compound <- unique(feature_to_compound, by = "id") |
| 67 | + # Join: unmatched mz_input rows keep the mz_rt_fallback ProteinName |
| 68 | + # set above. |
| 69 | + mz_input[ |
| 70 | + feature_to_compound, |
| 71 | + ProteinName := i.compound_name, |
| 72 | + on = setNames("id", id_col) |
| 73 | + ] |
66 | 74 | } |
67 | 75 |
|
68 | | - mz_input[, ProteinName := compound] |
69 | 76 | mz_input[, PeptideSequence := as.character(get(id_col))] |
70 | 77 |
|
71 | 78 | long <- data.table::melt( |
72 | 79 | mz_input, |
73 | 80 | id.vars = c("ProteinName", "PeptideSequence"), |
74 | 81 | measure.vars = peak_area_cols, |
75 | | - variable.name = "sample_col", |
| 82 | + variable.name = "Run", |
76 | 83 | value.name = "Intensity", |
77 | 84 | variable.factor = FALSE) |
78 | 85 |
|
79 | 86 | long[, PrecursorCharge := NA_integer_] |
80 | 87 | long[, FragmentIon := NA_character_] |
81 | 88 | long[, ProductCharge := NA_integer_] |
82 | | - long[, IsotopeLabelType := "Light"] |
83 | | - long[, Run := sub(paste0(peak_area_suffix, "$"), "", sample_col)] |
| 89 | + long[, Run := sub(paste0(peak_area_suffix, "$"), "", Run)] |
84 | 90 |
|
85 | 91 | final_cols <- c("ProteinName", "PeptideSequence", "PrecursorCharge", |
86 | | - "FragmentIon", "ProductCharge", "IsotopeLabelType", |
| 92 | + "FragmentIon", "ProductCharge", |
87 | 93 | "Run", "Intensity") |
88 | 94 | long <- long[, final_cols, with = FALSE] |
89 | 95 |
|
|
0 commit comments