Skip to content

Improve readQFeatures - #265

Draft
leopoldguyot wants to merge 4 commits into
rformassspectrometry:masterfrom
leopoldguyot:opti/readQFeatures
Draft

leopoldguyot wants to merge 4 commits into
rformassspectrometry:masterfrom
leopoldguyot:opti/readQFeatures

Conversation

@leopoldguyot

Copy link
Copy Markdown
Collaborator

@leopoldguyot

Copy link
Copy Markdown
Collaborator Author

For a subset of 500 cells (of 2310) from the data of Wu et al. 2026 (https://zenodo.org/records/22283331/files/peptide_report.tsv)
3 strategies:

  1. zero as NA and log transformation before import into QFeatures
        qfeat1 <- readQFeatures(subpep,
            runCol = "cellID",
            quantCols = c("Precursor.Quantity"),
            fnames = "Precursor.Id",
            zeroToNA = TRUE,
            logTransform = TRUE
        )
  1. zero as NA and log transformation after import into QFeatures
       qfeat2 <- readQFeatures(subpep,
            runCol = "cellID",
            quantCols = c("Precursor.Quantity"),
            fnames = "Precursor.Id",
            zeroToNA = FALSE,
            logTransform = FALSE
        )
        qfeat2 <- zeroIsNA(qfeat2, i = names(qfeat2))
        qfeat2 <- logTransform(qfeat2,
            i = names(qfeat2),
            name = paste0("log_", names(qfeat2))
        )
  1. zero as NA and log transformation before import into QFeatures + directly import the psms joined (some information are lost, ie. quality metrics specific to a run)
        metadata_cols <- subpep %>%
            group_by(Precursor.Id) %>%
            summarise(
                across(-c(cellID, Precursor.Quantity), ~
                    n_distinct(.x)),
                .groups = "drop"
            ) %>%
            select(-Precursor.Id) %>%
            select(where(~ all(.x == 1L))) %>%
            names()
        pep_wide <- subpep %>%
            pivot_wider(
                id_cols = all_of(c("Precursor.Id", metadata_cols)),
                names_from = cellID,
                values_from = Precursor.Quantity
            )
        qfeat3 <- readQFeatures(pep_wide,
            quantCols = unique(subpep$cellID),
            fnames = "Precursor.Id",
            zeroToNA = TRUE,
            logTransform = TRUE
        )
Elapsed_Time_sec Peak_RAM_Used_MiB
1 107.389 1902.5
2 1200.995 1903.5
3 22.032 1620.7

@leopoldguyot

Copy link
Copy Markdown
Collaborator Author

With multiple sets, we could split the data before importing it as a SummarizedExperiment.

@cvanderaa

Copy link
Copy Markdown
Collaborator

Two quick thoughts:

  • If log transformation becomes a default, we must be careful with the way CVs are computed. It should be computed on a linear scale, otherwise we need to adapt the CV formula (see here). I can't remember if QFeatures had a CV related function, but this is the case in scp. To be honest, we could also smply drop CVs, as I think there are quite some issues.
  • It seems you are doing this for computational efficiency. In fact, filtering would also be much faster if performed before the QFeatures object. I've seen script were part of the filtering is performed upstream readQfeatures, because it offers more flexibility (eg using tidyverse functions). I doesn't require any functionality on our side as it occurs upstream, but maybe usefull to document somewhere?

@leopoldguyot

leopoldguyot commented Sep 8, 2026 •

Copy link
Copy Markdown
Collaborator Author

Two quick thoughts:

  • If log transformation becomes a default, we must be careful with the way CVs are computed. It should be computed on a linear scale, otherwise we need to adapt the CV formula (see here). I can't remember if QFeatures had a CV related function, but this is the case in scp. To be honest, we could also smply drop CVs, as I think there are quite some issues.

Indeed, that is something we should be careful about. I am still not sure whether logTransform should be the default, as this would break existing scripts. Concerning CV, we could adapt the documentation of medianCVperCell or implement a version that is appropriate for log-transformed data.

  • It seems you are doing this for computational efficiency. In fact, filtering would also be much faster if performed before the QFeatures object. I've seen script were part of the filtering is performed upstream readQfeatures, because it offers more flexibility (eg using tidyverse functions). I doesn't require any functionality on our side as it occurs upstream, but maybe usefull to document somewhere?

Good point, I think it could be part of the vignette suggested here: UCLouvain-CBIO/scp#97 Still not sure if we should add a new vignette or improve others vignettes (eg. readSCP).

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants