NADIA 0.99.3
NADIA accepts five types of input: Spectronaut reports, DIA-NN protein-group
matrices, Proteome Discoverer TMT and LFQ reports, and SummarizedExperiment
objects prepared with other tools. Each has a dedicated importer:
preprocess_spectronaut(), preprocess_diann(), preprocess_tmt(),
preprocess_lfq() or preprocess_se(). All return the same proteomics_data
structure, so the imported data can follow a common processing and analysis
workflow.
This vignette applies each preprocessor to an example report and explains the main distinction among them: where NADIA obtains the experimental design. Correctly linking every measured column or run to its condition and replicate is essential, because that mapping determines the groups compared later in the analysis.
For example, preprocess_spectronaut() converts a long-format report—one row
for each reported combination of LC-MS run and protein group—into an object of
class proteomics_data.
The proteomics_data object separates the information contained in the source
report into three coordinated tables:
metadata contains one row per sample or LC-MS run, including the sample
identifier, experimental condition, replicate and any available run-level
information.
protein_id contains identification-level information for each protein group,
including protein and gene annotations and, when available, run-specific
evidence such as peptide and precursor counts, sequence coverage and
identification scores.
protein_quant contains the protein-level quantification data. It includes
the abundance measured for each protein group in each sample, together with
the protein annotations and quantitative evidence required by the downstream
workflow.
Figure 1: Five input sources converge on the common proteomics_data structure used by the NADIA workflow
In the Spectronaut example used below, metadata contains 12 samples, whereas
protein_id and protein_quant each contain 2,000 protein groups.
The three tables have distinct but complementary roles. metadata defines the
experimental design; protein_quant provides the abundance matrix used for
normalization, imputation and differential abundance analysis; and protein_id
retains the more detailed identification evidence used for inspection and
reporting.
if (!requireNamespace("BiocManager", quietly = TRUE))
install.packages("BiocManager")
BiocManager::install("NADIA")
library(NADIA)
NADIA provides a ready-to-use schema for generating a compatible Spectronaut report. Locate the installed file from R with:
system.file(“extdata”, “NADIA_Report.rs”, package = “NADIA”)
NADIA_Report.rs is a binary file interpreted by Spectronaut, not a text file
that lists the exported columns. Import it directly into Spectronaut and select
it when generating the report. The resulting table will contain the structure
and columns required by preprocess_spectronaut().
Spectronaut exports a long report: one row per protein group per run, with
the condition and replicate written in every row. Among the four input formats
supported by NADIA, Spectronaut is the only one for which the experimental
design does not need to be supplied separately. preprocess_spectronaut()
extracts it directly from the R.Condition and R.Replicate columns in the
report.
Figure 2: Structure of the long-format Spectronaut report accepted by preprocess_spectronaut()
The arguments accepted by preprocess_spectronaut() are summarized below. The
input report and the order of the conditions are required; the remaining
arguments control optional export and the aggregation of run-level annotations.
preprocess_spectronaut() call and default arguments
dia <- preprocess_spectronaut(
# Required input and experimental conditions
file_path = "spectronaut_report.tsv",
condition_order = c("Control", "Treatment"),
# Optional export; NULL keeps the result in memory
export_dir = NULL,
# Aggregation of annotations reported for multiple runs
agg_coverage_run = "max",
agg_coverage_global = "max",
agg_mw = "max",
agg_cscore_runwise = "mean",
# Exported file names and progress messages
timestamp_suffix = TRUE,
verbose = TRUE
)
dia_file <- system.file("extdata", "nadia_dia_report.tsv.gz", package = "NADIA")
dia <- preprocess_spectronaut(dia_file, condition_order = c("A", "B", "D"),
verbose = FALSE)
dia
#> Preprocessed Spectronaut data
#> -----------------------------
#> Runs (metadata): 12
#> Proteins (ID): 2000
#> Proteins (QUANT): 2000
#>
#> Conditions: A, B, D
Because the design already comes from the report, condition_order does not
infer or redefine the condition assigned to each run. Instead, it selects the
conditions to retain—excluding any other conditions present in the report—and
sets their order in the subsequent stages of the analysis, including downstream
comparisons. It should therefore list every condition that is to be analyzed.
The following output shows an example of the metadata table extracted and constructed from the imported Spectronaut report:
dia$metadata
#> R.FileName R.Condition R.Replicate Coding
#> A_1 20241014_XII_CursoProtQ_DIA_500ng_sample_A1 A 1 A_1
#> A_2 20241014_XII_CursoProtQ_DIA_500ng_sample_A2 A 2 A_2
#> A_3 20241014_XII_CursoProtQ_DIA_500ng_sample_A3 A 3 A_3
#> A_4 20241014_XII_CursoProtQ_DIA_500ng_sample_A4 A 4 A_4
#> B_1 20241014_XII_CursoProtQ_DIA_500ng_sample_B1 B 1 B_1
#> B_2 20241014_XII_CursoProtQ_DIA_500ng_sample_B2 B 2 B_2
#> B_3 20241014_XII_CursoProtQ_DIA_500ng_sample_B3 B 3 B_3
#> B_4 20241014_XII_CursoProtQ_DIA_500ng_sample_B4 B 4 B_4
#> D_1 20241014_XII_CursoProtQ_DIA_500ng_sample_D1 D 1 D_1
#> D_2 20241014_XII_CursoProtQ_DIA_500ng_sample_D2 D 2 D_2
#> D_3 20241014_XII_CursoProtQ_DIA_500ng_sample_D3 D 3 D_3
#> D_4 20241014_XII_CursoProtQ_DIA_500ng_sample_D4 D 4 D_4
#> R.PrecursorsIdentified R.StrippedSequencesIdentified R.ProteinGroupsIdentified
#> A_1 119383 92079 9999
#> A_2 118762 88994 9992
#> A_3 124304 94053 10101
#> A_4 118937 91948 10037
#> B_1 125709 94781 10213
#> B_2 127547 96821 10282
#> B_3 125104 95927 10233
#> B_4 120909 93568 10160
#> D_1 107757 82180 8597
#> D_2 107470 81586 8601
#> D_3 105982 81075 8612
#> D_4 102539 79005 8535
Because the report is long and run-level, the same protein group may have
multiple values for annotations such as sequence coverage, molecular weight and
C-score. The agg_* arguments determine how those values are reduced when a
single annotation value is required:
dia_median <- preprocess_spectronaut(
dia_file, condition_order = c("A", "B", "D"),
agg_coverage_run = "median", # default "max"
agg_cscore_runwise = "median", # default "mean"
verbose = FALSE)
These arguments affect only the annotations stored alongside the quantitative data; they do not modify protein intensities.
A DIA-NN protein-group matrix (report.pg_matrix.tsv) is wide: it contains
one row per protein group and one intensity column per run. This differs from
the long Spectronaut report and resembles the wide Proteome Discoverer exports
described below, which is why it requires a dedicated importer.
Figure 3: Structure of the wide DIA-NN protein-group matrix accepted by preprocess_diann()
The arguments accepted by preprocess_diann() are shown below. The report and
the condition order are required. annot_path is optional and is used when the
run columns do not follow the Abundance: <Condition>_<Replicate> convention.
preprocess_diann() call and default arguments
diann <- preprocess_diann(
# Required input and conditions to retain
file_path = "report.pg_matrix.tsv",
condition_order = c("Control", "Treatment"),
# Optional sample annotation file; NULL uses the column suffixes
annot_path = NULL,
# Optional export; NULL keeps the result in memory
export_dir = NULL,
timestamp_suffix = TRUE,
# Progress messages
verbose = TRUE
)
diann_file <- system.file("extdata", "nadia_diann_report.tsv.gz",
package = "NADIA")
diann <- preprocess_diann(diann_file, condition_order = c("A", "B", "D"),
verbose = FALSE)
diann
#> Preprocessed DIA-NN data
#> ------------------------
#> Runs (metadata): 12
#> Proteins (ID): 2000
#> Proteins (QUANT): 2000
#>
#> Conditions: A, B, D
DIA-NN names each intensity column after the raw file it came from:
D:\DIA-NN\Projects\20241014_XII_CursoProtQ_DIA_500ng_sample_A1.raw
The text sample_A1 may suggest condition A and replicate 1 to a reader, but
that interpretation depends on a laboratory-specific naming convention. A
regular expression that worked for this report could silently misclassify the
next one. NADIA therefore does not infer the design from raw-file names.
Instead, it can be declared in either of two ways:
Rename the run columns using the
Abundance: <Condition>_<Replicate> convention also used by Proteome
Discoverer. The example distributed with NADIA follows this convention, so
the call above needs no additional argument.
Supply an annotation file through annot_path and leave the report
exactly as DIA-NN exported it. The Column field must contain the complete
run headers, including the raw-file paths:
preprocess_diann(
"report.pg_matrix.tsv",
condition_order = c("A", "B", "D"),
annot_path = "design.tsv")
design.tsv must be a tab-separated file with one row for each run that should
be imported and two columns named exactly Column and Condition. Column
contains the complete header of the corresponding intensity column in the
DIA-NN matrix, while Condition assigns that run to an experimental group. For
example:
Column Condition
D:\DIA-NN\Projects\experiment\sample_A1.raw A
D:\DIA-NN\Projects\experiment\sample_A2.raw A
D:\DIA-NN\Projects\experiment\sample_B1.raw B
The values in Column must match the report headers exactly, including the
complete raw-file path when DIA-NN uses paths as column names. Runs omitted from
the annotation file are not imported. condition_order then selects which of
the annotated conditions are retained and sets their order in the subsequent
analysis. If neither valid Abundance: <Condition>_<Replicate> headers nor an
annotation file are supplied, the error message lists the headers that must be
entered in Column.
Whichever route is used, NADIA constructs one row of metadata per retained
run. The columns have the following meaning:
R.FileName preserves the complete intensity-column header read from the
report.R.Condition contains the experimental condition, obtained either from the
renamed header or from Condition in the annotation file.R.Replicate is read from a <Condition>_<Replicate> suffix when that naming
convention is used. For original DIA-NN headers without such a suffix, runs
are numbered sequentially within each condition.Coding is the sample identifier used to name the quantitative columns. It
is the <Condition>_<Replicate> suffix for renamed columns and the value of
Column when annot_path is used.R.ProteinGroupsIdentified reports how many protein groups have a non-missing
intensity in that run.The following output shows an example of the metadata table extracted and constructed from the imported DIA-NN report:
diann$metadata
#> R.FileName R.Condition R.Replicate Coding R.ProteinGroupsIdentified
#> A_1 Abundance: A_1 A 1 A_1 1854
#> A_2 Abundance: A_2 A 2 A_2 1813
#> A_3 Abundance: A_3 A 3 A_3 1860
#> A_4 Abundance: A_4 A 4 A_4 1831
#> B_1 Abundance: B_1 B 1 B_1 1865
#> B_2 Abundance: B_2 B 2 B_2 1888
#> B_3 Abundance: B_3 B 3 B_3 1856
#> B_4 Abundance: B_4 B 4 B_4 1850
#> D_1 Abundance: D_1 D 1 D_1 1550
#> D_2 Abundance: D_2 D 2 D_2 1547
#> D_3 Abundance: D_3 D 3 D_3 1548
#> D_4 Abundance: D_4 D 4 D_4 1538
Note on identification information. The DIA-NN protein-group matrix contains
little identification evidence. The two available fields are N.Sequences,
which gives the total peptide-sequence count, and
N.Proteotypic.Sequences, which gives the proteotypic peptide count. To
preserve the common structure of the proteomics_data object, NADIA repeats
these protein-level values across runs in protein_id, as it does for the
global Proteome Discoverer metrics in TMT data. NADIA also calculates the
number of protein groups with a reported intensity in each run and stores it as
R.ProteinGroupsIdentified in the metadata table shown above.
A TMT report from Proteome Discoverer is wide: it contains one row per
protein group and one abundance column per sample. As with DIA-NN, the
experimental design must be declared either through column names that follow
the Abundance: <Condition>_<Replicate> convention or through an annotation
file supplied with annot_path.
Figure 4: Structure of the wide Proteome Discoverer TMT report accepted by preprocess_tmt()
The arguments accepted by preprocess_tmt() are listed below. The report and
the conditions to retain are required. annot_path provides an alternative
way to declare the design when the abundance suffixes do not follow the naming
convention.
preprocess_tmt() call and default arguments
tmt <- preprocess_tmt(
# Required input and conditions to retain
file_path = "tmt_report.tsv",
condition_order = c("Control", "Treatment"),
# Optional channel annotation file; NULL uses the column suffixes
annot_path = NULL,
# Optional export; NULL keeps the result in memory
export_dir = NULL,
timestamp_suffix = TRUE,
# Progress messages
verbose = TRUE
)
The design can be supplied in either of two ways:
Use informative abundance-column suffixes. Columns named
Abundance: A_1, Abundance: A_2 and Abundance: B_1, for example, identify
the condition and replicate directly. No annotation file is required.
Supply an annotation file. This is useful when the abundance columns
retain identifiers such as the TMT tags 126, 127N or 127C. The
annotation file assigns each identifier to its experimental condition
without modifying the Proteome Discoverer report.
design.tsv must be a tab-separated file with the columns Column and
Condition. For TMT data, Column contains the exact text that follows the
Abundance: prefix in the report. For example:
Column Condition
126 A
127N A
127C B
128N B
128C D
129N D
Thus, an abundance column named Abundance: 127N is identified by the value
127N in Column. Identifiers omitted from the annotation file are not
imported. condition_order subsequently selects the conditions to retain and
sets their order in the downstream analysis. The annotation file is passed to
preprocess_tmt() as follows:
preprocess_tmt(
"tmt_report.tsv",
condition_order = c("A", "B", "D"),
annot_path = "design.tsv")
This example contains three biological conditions with eight replicates each,
plus four IS channels that provide an internal standard across two TMT mixes.
Replicates 1–4 belong to the first mix and replicates 5–8 to the second.
Because condition_order also filters the parsed channels, omitting "IS"
excludes the standards and prevents NADIA from treating them as a biological
condition in downstream contrasts:
tmt_file <- system.file("extdata", "nadia_tmt_report.tsv.gz", package = "NADIA")
tmt <- preprocess_tmt(tmt_file, condition_order = c("A", "B", "D"),
verbose = FALSE)
tmt
#> Preprocessed TMT (Proteome Discoverer) data
#> ------------------------------------------
#> Channels (metadata): 24
#> Proteins (ID): 2000
#> Proteins (QUANT): 2000
#>
#> Conditions: A, B, D
The following output shows an example of the metadata table extracted and
constructed from the imported TMT report. The condition counts confirm that the
IS channels were excluded by condition_order:
head(tmt$metadata)
#> R.FileName R.Condition R.Replicate Coding
#> A_1 Abundance: A_1 A 1 A_1
#> A_2 Abundance: A_2 A 2 A_2
#> A_3 Abundance: A_3 A 3 A_3
#> A_4 Abundance: A_4 A 4 A_4
#> A_5 Abundance: A_5 A 5 A_5
#> A_6 Abundance: A_6 A 6 A_6
table(tmt$metadata$R.Condition)
#>
#> A B D
#> 8 8 8
Note on identification information. TMT samples are digested and labeled
individually, but they are then combined and analyzed as a multiplexed mixture.
Consequently, the identification evidence reported by Proteome Discoverer is
global to the multiplex rather than specific to each original sample. To
preserve the common structure of the proteomics_data object, NADIA repeats
global values such as the numbers of PSMs and identified peptides, sequence
coverage and the PEP score across the samples in protein_id. These repeated
values must not be interpreted as independent sample-level identifications. In
contrast, the reporter-ion abundances are sample-specific and remain separate
in protein_quant.
Any additional columns in design.tsv are ignored. Batch, TMT/LFQ experiment
and other covariate information should instead be supplied through
covariate_df in process_proteomics(), as explained in
vignette("batch-correction").
A label-free report from Proteome Discoverer is wide: it contains one row
per protein group and one abundance column per sample. As with DIA-NN and TMT,
the experimental design can be obtained from column names that follow the
Abundance: <Condition>_<Replicate> convention or supplied separately through
annot_path.
Figure 5: Structure of the wide Proteome Discoverer LFQ report accepted by preprocess_lfq()
Unlike DIA-NN and TMT, but like Spectronaut, this report contains
per-sample identification metrics. For every sample, Proteome Discoverer
can report a Mascot score, a PSM count and a peptide count in addition to the
abundance. NADIA matches these column families to the corresponding sample by
name rather than by their position in the report. The resulting identification
values therefore retain differences among samples in protein_id.
The arguments accepted by preprocess_lfq() are shown below. Only the report is
required. Both annot_path and condition_order are optional; when omitted,
the design and condition order are obtained from the abundance suffixes.
preprocess_lfq() call and default arguments
lfq <- preprocess_lfq(
# Required input
file_path = "lfq_report.tsv",
# Optional design file and condition filtering/order
annot_path = NULL,
condition_order = NULL,
# Optional export; NULL keeps the result in memory
export_dir = NULL,
timestamp_suffix = TRUE,
# Progress messages
verbose = TRUE
)
The design can be supplied in either of two ways:
Use informative abundance-column suffixes. Columns named
Abundance: A_1, Abundance: A_2 and Abundance: B_1, for example, identify
the condition and replicate directly. This is the convention used by the
example report distributed with NADIA.
Supply an annotation file. This route is used when the text after
Abundance: identifies a sample but does not encode its experimental
condition and replicate. The report itself does not need to be renamed.
design.tsv must be a tab-separated file with the columns Column and
Condition. Column contains the exact sample identifier that follows the
Abundance: prefix in the report. For example:
Column Condition
Sample01 Control
Sample02 Control
Sample03 Treatment
Sample04 Treatment
Thus, the abundance column Abundance: Sample01 is identified by Sample01 in
Column. Samples omitted from the annotation file are not imported. If
condition_order is supplied, it additionally selects the conditions to
retain and sets their order; otherwise, NADIA uses their order of appearance.
The annotation file is passed to preprocess_lfq() as follows:
preprocess_lfq(
"lfq_report.tsv",
condition_order = c("Control", "Treatment"),
annot_path = "design.tsv")
The example report distributed with NADIA contains three conditions with four
replicates each. Its abundance-column suffixes already encode the complete
design, so neither annot_path nor condition_order needs to be supplied:
lfq_file <- system.file("extdata", "nadia_lfq_report.tsv.gz", package = "NADIA")
lfq <- preprocess_lfq(lfq_file, verbose = FALSE)
lfq
#> Preprocessed LFQ (Proteome Discoverer) data
#> ------------------------------------------
#> Samples (metadata): 12
#> Proteins (ID): 2000
#> Proteins (QUANT): 2000
#>
#> Conditions: A, B, D
The following output shows an example of the metadata table extracted and constructed from the imported LFQ report:
lfq$metadata
#> R.FileName R.Condition R.Replicate Coding
#> A_1 Abundance: A_1 A 1 A_1
#> A_2 Abundance: A_2 A 2 A_2
#> A_3 Abundance: A_3 A 3 A_3
#> A_4 Abundance: A_4 A 4 A_4
#> B_1 Abundance: B_1 B 1 B_1
#> B_2 Abundance: B_2 B 2 B_2
#> B_3 Abundance: B_3 B 3 B_3
#> B_4 Abundance: B_4 B 4 B_4
#> D_1 Abundance: D_1 D 1 D_1
#> D_2 Abundance: D_2 D 2 D_2
#> D_3 Abundance: D_3 D 3 D_3
#> D_4 Abundance: D_4 D 4 D_4
Any additional columns in design.tsv are ignored. Batch, TMT/LFQ experiment
and other covariate information should instead be supplied through
covariate_df in process_proteomics(), as explained in
vignette("batch-correction").
Protein intensities prepared with other Bioconductor tools can be supplied in a
SummarizedExperiment, for instance a protein-level assay of a QFeatures
object. preprocess_se() converts one into the same proteomics_data object,
and process_proteomics() can call this importer automatically when given a
SummarizedExperiment. NADIA needs three things from the object:
log2_input = TRUE;colData()$Condition, with the replicate in
colData()$Replicate or, without that column, numbered within each
condition.Use assay_name to select an assay when the object contains several; otherwise,
the first assay is used.
Gene names and descriptions are read from rowData()$Genes and
rowData()$Description when present. The samples are renamed
<condition>_<replicate>, as the other readers do, and the original names are
kept in metadata$R.FileName.
quant_cols <- grep("^PG.Quantity_", names(dia$protein_quant))
log2_intensities <- log2(as.matrix(dia$protein_quant[, quant_cols]))
rownames(log2_intensities) <- dia$protein_quant$PG.ProteinGroups
se <- SummarizedExperiment::SummarizedExperiment(
assays = list(log2 = log2_intensities),
colData = data.frame(Condition = dia$metadata$R.Condition))
from_se <- preprocess_se(se, log2_input = TRUE, verbose = FALSE)
from_se
#> Protein intensities imported from a SummarizedExperiment
#> --------------------------------------------------------
#> Samples (metadata): 12
#> Proteins: 2000
#>
#> Conditions: A, B, D
head(from_se$metadata[, c("R.FileName", "R.Condition", "R.Replicate", "Coding")])
#> R.FileName R.Condition R.Replicate Coding
#> A_1 PG.Quantity_A_1 A 1 A_1
#> A_2 PG.Quantity_A_2 A 2 A_2
#> A_3 PG.Quantity_A_3 A 3 A_3
#> A_4 PG.Quantity_A_4 A 4 A_4
#> B_1 PG.Quantity_B_1 B 1 B_1
#> B_2 PG.Quantity_B_2 B 2 B_2
This importer does not transfer identification metrics from rowData(): the
precursor counts of protein_id are left empty, and no peptide counts or
scores are created, so the interactive tables show only the quantities. The
quantitative analysis is unaffected.
All five importers produce a common object, but the location of the experimental design depends on the input. NADIA must know which condition and replicate correspond to each sample:
| Input | Where the design is stored |
|---|---|
| Spectronaut | R.Condition and R.Replicate in the long report |
| DIA-NN | Run-column suffixes, or an annotation file supplied through annot_path |
| TMT (PD) | Abundance-column suffixes, or annot_path |
| LFQ (PD) | Abundance-column suffixes, or annot_path |
SummarizedExperiment |
Condition and, optionally, Replicate in colData() |
Spectronaut carries the design within its report. For the three wide report
formats, use the Abundance: <condition>_<replicate> naming convention or a
two-column annotation file. DIA-NN matches the file’s Column values against
complete run headers; the Proteome Discoverer importers match them against the
text after Abundance:.
For a SummarizedExperiment, conditions come from colData()$Condition.
Replicates come from colData()$Replicate when available; otherwise they are
numbered within each condition. With preprocess_se(), condition_column and
replicate_column allow these fields to have other names. No annotation file
is needed.
condition_order selects the conditions to retain and determines their order
in the analysis. It is required by the Spectronaut, DIA-NN and TMT importers,
and optional for LFQ and preprocess_se(). LFQ defaults to order of appearance;
preprocess_se() uses the condition factor’s levels, or order of appearance
when the condition is not a factor.
Regardless of the input format, condition names become column names in the
design matrix. The differential abundance model evaluates a contrast such as
"B-A" as the expression B - A; it is not only a display label.
This determines which condition names are safe. For example, conditions named
Tr-1 and Ct-1 would produce Tr-1-Ct-1. R would interpret the hyphens as
several subtraction operators rather than as characters within two condition
names, so the intended contrast could not be constructed.
The rule is simple: each condition must have a syntactically valid R name. In practice:
| In the name | Verdict | Why |
|---|---|---|
| letters, digits (not first) | fine | Ctrl, Treat24h |
. full stop |
fine | Ct.1 gives the contrast Tr.1-Ct.1 |
_ underscore |
fine | Ct_a gives Tr_a-Ct_a |
- hyphen |
rejected | collides with the contrast separator |
| space | rejected | not a syntactic name |
| leading digit | rejected | 1Ct is not a name; R would rewrite it X1Ct |
Names that follow the rows marked fine can be used safely and allow the
pipeline to complete without naming-related errors. If there is any doubt,
consult the table above or check the proposed names with make.names():
candidates <- c("Ctrl", "Ct.1", "Ct_a", "Ct-1", "Ct 1", "1Ct")
data.frame(name = candidates,
valid = make.names(candidates) == candidates,
what_r_would_do = make.names(candidates))
#> name valid what_r_would_do
#> 1 Ctrl TRUE Ctrl
#> 2 Ct.1 TRUE Ct.1
#> 3 Ct_a TRUE Ct_a
#> 4 Ct-1 FALSE Ct.1
#> 5 Ct 1 FALSE Ct.1
#> 6 1Ct FALSE X1Ct
The pipeline validates condition names before fitting the model and stops with
an informative error if any are invalid. Sample identifiers must also remain
consistent. A Column value in design.tsv that does not match the report
produces an error, whereas samples omitted from the annotation file are
excluded. If metadata$Coding is subsequently edited and no longer matches the
corresponding PG.Quantity_<coding> column, the unmatched samples are removed
from the analysis and the result contains fewer samples than expected.
In all three wide formats, the shared suffix parser reads the replicate from
the trailing digits of <condition>_<replicate>. An underscore within the
condition remains valid: Ct_a_1 is parsed as condition Ct_a, replicate 1.
When annot_path is used, the labels in its Condition field define the
experimental conditions. A condition label can therefore be corrected in
design.tsv without renaming any abundance column in the quantitative report;
the values in Column must still match the corresponding report identifiers.
The five importers convert their inputs into a proteomics_data object.
Each retains a source-specific class, while sharing the same three components:
metadata, protein_id and protein_quant. The following comparison includes
the SummarizedExperiment imported above:
inputs <- list(Spectronaut = dia, DIA_NN = diann, TMT = tmt, LFQ = lfq,
SummarizedExperiment = from_se)
vapply(inputs, function(x) class(x)[1], character(1))
#> Spectronaut DIA_NN TMT LFQ
#> "spectronaut_data" "diann_data" "tmt_data" "lfq_data"
#> SummarizedExperiment
#> "se_data"
vapply(inputs, function(x) inherits(x, "proteomics_data"), logical(1))
#> Spectronaut DIA_NN TMT LFQ
#> TRUE TRUE TRUE TRUE
#> SummarizedExperiment
#> TRUE
lapply(inputs, names)
#> $Spectronaut
#> [1] "metadata" "protein_id" "protein_quant"
#>
#> $DIA_NN
#> [1] "metadata" "protein_id" "protein_quant"
#>
#> $TMT
#> [1] "metadata" "protein_id" "protein_quant"
#>
#> $LFQ
#> [1] "metadata" "protein_id" "protein_quant"
#>
#> $SummarizedExperiment
#> [1] "metadata" "protein_id" "protein_quant"
metadata links each sample to its condition, replicate and quantitative
columns. Additional fields depend on the source: Spectronaut includes detailed
run-level identification counts, whereas the other inputs may provide fewer
annotations. The shared structure does not imply that every source supplies
the same evidence:
lapply(inputs, function(x) colnames(x$metadata))
#> $Spectronaut
#> [1] "R.FileName" "R.Condition" "R.Replicate"
#> [4] "Coding" "R.PrecursorsIdentified" "R.StrippedSequencesIdentified"
#> [7] "R.ProteinGroupsIdentified"
#>
#> $DIA_NN
#> [1] "R.FileName" "R.Condition" "R.Replicate"
#> [4] "Coding" "R.ProteinGroupsIdentified"
#>
#> $TMT
#> [1] "R.FileName" "R.Condition" "R.Replicate" "Coding"
#>
#> $LFQ
#> [1] "R.FileName" "R.Condition" "R.Replicate" "Coding"
#>
#> $SummarizedExperiment
#> [1] "R.FileName" "R.Condition" "R.Replicate"
#> [4] "Coding" "R.ProteinGroupsIdentified"
NADIA uses common column names for identification metrics. Most follow the
Spectronaut convention, while scores use neutral names. The suffix * below
identifies a sample; the global score is stored in protein_quant.
| Metric | NADIA column |
|---|---|
| Precursor or PSM count | PG.NrOfPrecursorsIdentified_* |
| Sequence or peptide count | PG.NrOfStrippedSequencesIdentified_* |
| Sequence coverage | PG.Coverage_* |
| Sample-level score | PG.Score.RunWise_* |
| Global score | PG.Score |
The meaning and availability of these fields depend on the input:
PG.Cscore (Run-Wise) provide the sample-level metrics; PG.Cscore supplies
the global score.N.Sequences supplies the sequence count. Precursor counts are
empty; coverage and score columns are not created.# PSMs, # Peptides, Coverage [%] and
Sum PEP Score supply the metrics. These are protein-level totals repeated
across channels, not independent identifications for each channel.
Sum PEP Score also supplies the global score.# PSMs (by Search Engine),
# Peptides (by Search Engine) and Score Mascot columns provide counts and
scores. Protein-level Coverage [%] is repeated across samples, and
Sum PEP Score supplies the global score.rowData(). Precursor counts remain empty; peptide counts,
coverage and scores are not created. Gene names and descriptions are read
when the corresponding annotation fields are present.A common column name does not make these metrics equivalent: PSM counts are
not precursor counts, and scores from different engines do not share a scale.
NADIA records the original score name in nadia_labels, which interactive
tables use for their column labels:
lapply(inputs, function(x) attr(x$protein_quant, "nadia_labels"))
#> $Spectronaut
#> PG.Score
#> "Cscore"
#>
#> $DIA_NN
#> NULL
#>
#> $TMT
#> PG.Score
#> "Sum PEP Score"
#>
#> $LFQ
#> PG.Score
#> "Sum PEP Score"
#>
#> $SummarizedExperiment
#> NULL
For every input, each sample’s abundances are stored in a
PG.Quantity_<Coding> column linked to metadata$Coding. This common mapping
allows all five objects to enter the same processing workflow, even when their
identification annotations differ:
processed <- lapply(inputs, process_proteomics, verbose = FALSE)
lapply(processed, function(x) x$comparisons)
#> $Spectronaut
#> [1] B-A D-A D-B
#> Levels: B-A D-A D-B
#>
#> $DIA_NN
#> [1] B-A D-A D-B
#> Levels: B-A D-A D-B
#>
#> $TMT
#> [1] B-A D-A D-B
#> Levels: B-A D-A D-B
#>
#> $LFQ
#> [1] B-A D-A D-B
#> Levels: B-A D-A D-B
#>
#> $SummarizedExperiment
#> [1] B-A D-A D-B
#> Levels: B-A D-A D-B
The same downstream functions perform normalization, imputation, differential
abundance analysis and visualization. Their results depend on the supplied
quantities and analysis settings, rather than on the availability of optional
identification metrics. See vignette("results-and-export") for presentation
and export of the results.
sessionInfo()
#> R version 4.6.1 (2026-06-24)
#> Platform: x86_64-pc-linux-gnu
#> Running under: Ubuntu 24.04.5 LTS
#>
#> Matrix products: default
#> BLAS: /home/biocbuild/bbs-3.24-bioc/R/lib/libRblas.so
#> LAPACK: /usr/lib/x86_64-linux-gnu/lapack/liblapack.so.3.12.0 LAPACK version 3.12.0
#>
#> locale:
#> [1] LC_CTYPE=en_US.UTF-8 LC_NUMERIC=C LC_TIME=en_GB
#> [4] LC_COLLATE=C LC_MONETARY=en_US.UTF-8 LC_MESSAGES=en_US.UTF-8
#> [7] LC_PAPER=en_US.UTF-8 LC_NAME=C LC_ADDRESS=C
#> [10] LC_TELEPHONE=C LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=C
#>
#> time zone: America/New_York
#> tzcode source: system (glibc)
#>
#> attached base packages:
#> [1] stats4 stats graphics grDevices utils datasets methods base
#>
#> other attached packages:
#> [1] SummarizedExperiment_1.43.0 Biobase_2.73.2 GenomicRanges_1.65.4
#> [4] Seqinfo_1.3.2 IRanges_2.47.5 S4Vectors_0.51.10
#> [7] BiocGenerics_0.59.13 generics_0.1.4 MatrixGenerics_1.25.0
#> [10] matrixStats_1.5.0 NADIA_0.99.3 BiocStyle_2.41.0
#>
#> loaded via a namespace (and not attached):
#> [1] RColorBrewer_1.1-3 jsonlite_2.0.0 shape_1.4.6.1 magrittr_2.0.5
#> [5] magick_2.9.1 farver_2.1.2 nloptr_2.2.1 rmarkdown_2.32
#> [9] GlobalOptions_0.1.4 vctrs_0.7.3 memoise_2.0.1 Cairo_1.7-0
#> [13] minqa_1.2.8 janitor_2.2.1 BiocBaseUtils_1.15.1 htmltools_0.5.9
#> [17] S4Arrays_1.13.2 curl_8.1.0 broom_1.0.13 pROC_1.19.1
#> [21] SparseArray_1.13.4 TTR_0.24.4 sass_0.4.10 bslib_0.12.0
#> [25] htmlwidgets_1.6.4 sandwich_3.1-3 impute_1.87.0 zoo_1.9-1
#> [29] lubridate_1.9.5 cachem_1.1.0 lifecycle_1.0.5 iterators_1.0.14
#> [33] pkgconfig_2.0.3 Matrix_1.7-6 R6_2.6.1 fastmap_1.2.0
#> [37] rbibutils_2.4.1 snakecase_0.11.1 clue_0.3-68 digest_0.6.39
#> [41] pcaMethods_2.5.0 colorspace_2.1-4 tidyHeatmap_1.13.1 AnnotationDbi_1.75.2
#> [45] patchwork_1.3.2 RSQLite_3.53.3 rrcovNA_0.5-3 vegan_2.7-6
#> [49] labeling_0.4.3 timechange_0.4.0 mgcv_1.9-5 httr_1.4.9
#> [53] abind_1.4-8 compiler_4.6.1 bit64_4.8.6 withr_3.0.3
#> [57] doParallel_1.0.17 S7_0.2.2 backports_1.5.1 BiocParallel_1.47.0
#> [61] DBI_1.3.0 viridis_0.6.5 dendextend_1.19.1 MASS_7.3-66
#> [65] DelayedArray_0.39.8 rjson_0.2.23 permute_0.10-0 tools_4.6.1
#> [69] rrcov_1.7-7 otel_0.3.0 quantmod_0.4.29 glue_1.8.1
#> [73] nlme_3.1-172 grid_4.6.1 cluster_2.1.8.3 sva_3.61.0
#> [77] gtable_0.3.6 tidyr_1.3.2 data.table_1.18.6.1 XVector_0.53.0
#> [81] foreach_1.5.2 pillar_1.11.1 stringr_1.6.0 limma_3.99.4
#> [85] genefilter_1.95.0 gmm_1.9-1 logging_0.10-111 robustbase_0.99-7
#> [89] circlize_0.4.18 splines_4.6.1 dplyr_1.2.1 lattice_0.23-1
#> [93] survival_3.8-12 bit_4.6.0 annotate_1.91.1 tidyselect_1.2.1
#> [97] ComplexHeatmap_2.29.0 Biostrings_2.81.9 knitr_1.52 BERT_1.9.0
#> [101] reformulas_0.4.4 gridExtra_2.3.1 bookdown_0.48 imputeLCMD_2.1
#> [105] edgeR_4.99.12 xfun_0.62 statmod_1.5.2 DEoptimR_1.2-2
#> [109] stringi_1.8.9 yaml_2.3.12 boot_1.3-32 evaluate_1.0.5
#> [113] codetools_0.2-20 MsCoreUtils_1.25.4 tibble_3.3.1 BiocManager_1.30.27
#> [117] cli_3.6.6 xtable_1.8-8 Rdpack_2.6.6 jquerylib_0.1.4
#> [121] dichromat_2.0-1 Rcpp_1.1.2 norm_1.0-11.1 png_0.1-9
#> [125] XML_3.99-0.25 parallel_4.6.1 blob_1.3.0 ggplot2_4.0.3
#> [129] assertthat_0.2.1 lme4_2.1-0 viridisLite_0.4.3 mvtnorm_1.4-2
#> [133] rlist_0.4.6.2 tmvtnorm_1.7 scales_1.4.0 xts_0.14.3
#> [137] pcaPP_2.0-7 purrr_1.2.2 highcharter_0.9.5 crayon_1.5.3
#> [141] GetoptLong_1.1.1 rlang_1.3.0 KEGGREST_1.53.6