Bottom-up mass spectrometry (MS) is an effective tool for analyzing high-throughput proteomics. This method allows the proteome of cells, tissues and organisms to be investigated in depth. It allows diseases such as Parkinson’s and the effects of stress on cells and organisms to be studied at a proteomic level. In bottom-up MS, however, proteins are digested into smaller peptides, which are then measured. Consequently, the measured intensities correspond to peptides rather than proteins. While this makes differential analysis at the peptide level possible, it lacks biological interpretability. Peptide intensities can instead be aggregated to protein intensities, but this is not straightforward due to shared peptides.
Our package, bppg (bipartite
peptide protein
graphs), is designed to utilize all peptide-level
information for protein quantification. This is achieved by modelling
the relationship between the quantified peptides and their proteins of
origin using bipartite graphs. These graphs form the basis of an
equation system to which an optimization method is applied to provide
the best explanation of the measured ratios using the optimized protein
ratios.
The functions and steps of the workflow, from peptide quantities to relative protein quantifications, include:
In this vignette we included a quick start guide to use
bppg.
There are two categories of peptides. First, unique peptides, which originate from one protein or protein group (proteins that cannot be distinguished based on the measured peptides). Second, shared peptides, which can derive from more than one protein/protein group. Unique peptides are strong evidence for the presence of a protein and shared peptides provide ambiguous information. (Schork, 2024)
In a bipartite graph, there are two types of nodes (in this case, proteins and peptides) and edges only exist between different types, never within one type of group. A protein node is connected to all their possible peptide products. Unique peptides therefore have only one edge, while shared peptides have several. This graph can be based on only in silico information, creating a theoretical graph. (Schork, 2024)
This example shows two proteins, which share one peptide and also
each have an unique peptide.
bppgTo install the latest version of bppg from Bioconductor
use the following code snippet:
If you need help with bppg, encounter a bug or have
suggestions for improvements leave a post in the Bioconductor support site
with the bppg tag or start an issue on our github page.
bppgWe hope that bppg will be useful for your research. Please use the following information to cite the package and the overall approach. Thank you!
## Citation info
citation("bppg")
#> To cite package 'bppg' in publications use:
#>
#> Schork K, Wenzel J, Neuhaus K, Eisenacher M (2026). _bppg: Bipartite
#> peptide-protein graphs_.
#> <https://github.com/mpc-bioinformatics/bppg>.
#>
#> Schork K (2024). _Improvement of protein quantification for proteins
#> with shared peptides by using bipartite peptide-protein graphs_.
#> Ph.D. thesis, TU Dortmund University. doi:10.17877/DE290R-25361
#> <https://doi.org/10.17877/DE290R-25361>.
#>
#> To see these entries in BibTeX format, use 'print(<citation>,
#> bibtex=TRUE)', 'toBibtex(.)', or set
#> 'options(citation.bibtex.max=999)'.bppgThe main task of bppg is protein inference and relative
protein quantification for bottom-up mass spectrometry. This method is
only suitable for relative analysis. Therefore, at least two samples are
required to calculate the protein quantities. However, at least 3
replicates per group are recommended.
Required inputs:
colData and peptide information in
rowDataA test dataset and the matching FASTA file are provided within the package. It is a subset of a benchmark dataset which was created to determine the correctness of protein quantification software (Ramus, Hovasse, Marcellin, Hesse, Mouton-Barbosa, Bouyssié, Vaca, Carapito, Chaoui, Bruley, Garin, Cianférani, Ferro, Dorssaeler, Burlet-Schiltz, Schaeffer, Couté, and Gonzalez de Peredo, 2016). The original dataset includes:
The example data used in this vignette includes peptides from 9 yeast proteins.
The peptide quantification was performed with MaxQuant (version
2.7.3.0) and resulted in a peptides.txt file. The
corresponding function to extract the columns of interest is
readMqPeptideTable, this includes the peptide sequences and
intensity values.
library("bppg")
library("SummarizedExperiment")
file <- system.file("extdata", "peptides_filtered.txt", package = "bppg")
D <- readMqPeptideTable(path = file)Here is an example of the structure in our SummarizedExperiment dataset:
D # SummarizedExperiment overview
#> class: SummarizedExperiment
#> dim: 87 27
#> metadata(0):
#> assays(1): intensities
#> rownames(87): AAADALSDLEIK AAADALSDLEIKDSK ... NMVSDIQEATK VLGIDAGEEK
#> rowData names(1): Sequence
#> colnames(27): 12500amol_R1 12500amol_R2 ... 00050amol_R2 00050amol_R3
#> colData names(1): sample
head(colData(D)) # sample/replicate metadata
#> DataFrame with 6 rows and 1 column
#> sample
#> <character>
#> 12500amol_R1 12500amol_R1
#> 12500amol_R2 12500amol_R2
#> 12500amol_R3 12500amol_R3
#> 00125amol_R1 00125amol_R1
#> 00125amol_R2 00125amol_R2
#> 00125amol_R3 00125amol_R3
assays(D)$intensities[1:5, 1:3] # peptide intensity matrix
#> 12500amol_R1 12500amol_R2 12500amol_R3
#> AAADALSDLEIK NA NA NA
#> AAADALSDLEIKDSK 8047500 7759800 5142900
#> AEWALR 5203200 4754000 4987700
#> DEGLHTDFACLLFAHLK 4653600 3640300 484990
#> DIHDWNNR 1983600 1838600 NA
head(rowData(D)) # peptide metadata (sequence, protein, etc.)
#> DataFrame with 6 rows and 1 column
#> Sequence
#> <character>
#> AAADALSDLEIK AAADALSDLEIK
#> AAADALSDLEIKDSK AAADALSDLEIKDSK
#> AEWALR AEWALR
#> DEGLHTDFACLLFAHLK DEGLHTDFACLLFAHLK
#> DIHDWNNR DIHDWNNR
#> ELETLREENR ELETLREENRTo build the bipartite graph, proteins need to be digested in silico and peptides matched with their protein of origin. For this we have a reduced FASTA file.
library(seqinr)
file <- system.file("extdata", "uniprot_proteome_Scerevisiae_filtered.fasta",
package = "bppg")
fasta <- seqinr::read.fasta(file = file, seqtype = "AA", as.string = TRUE)
names(fasta)
#> [1] "sp|P09938|RIR2_YEAST" "sp|P39708|DHE5_YEAST" "sp|P07262|DHE4_YEAST"
#> [4] "sp|P40212|RL13B_YEAST" "sp|Q12690|RL13A_YEAST" "sp|P00330|ADH1_YEAST"
#> [7] "sp|P00331|ADH2_YEAST" "sp|P07246|ADH3_YEAST" "sp|P38113|ADH5_YEAST"Now the theoretical information can be combined with quantification
data into a bipartite peptide protein graph. To simplify this, we
created a wrapper function, which includes digestion and data
preprocessing (normalization, replicate aggregation and ratio
calculation). To generate the quantification graphs, the protein nodes
are collapsed (collProtNodes = TRUE), this creates protein
groups of proteins which contain the same measured peptides.
The graph created for each comparison is not fully interconnected but
many independent graphs which are considered separately in the
downstream analysis. Therefore, graphs is a nested list,
first on the level of comparisons and then the multitude of independent
graphs for that comparison.
graphs[[1]][[3]] shows one graph of the first comparison
50 amol vs 125 amol. The igraph object shows the amount of
nodes and edges, the attributes and the first edges. This example is
from the RIR2 protein which does not have an overlap with another
protein. The peptide nodes show the respective log2-transformed peptide
ratios.
names(graphs)
#> [1] "00050amol_00125amol" "00050amol_00250amol" "00050amol_00500amol"
#> [4] "00050amol_02500amol" "00050amol_05000amol" "00050amol_12500amol"
#> [7] "00050amol_25000amol" "00050amol_50000amol" "00125amol_00250amol"
#> [10] "00125amol_00500amol" "00125amol_02500amol" "00125amol_05000amol"
#> [13] "00125amol_12500amol" "00125amol_25000amol" "00125amol_50000amol"
#> [16] "00250amol_00500amol" "00250amol_02500amol" "00250amol_05000amol"
#> [19] "00250amol_12500amol" "00250amol_25000amol" "00250amol_50000amol"
#> [22] "00500amol_02500amol" "00500amol_05000amol" "00500amol_12500amol"
#> [25] "00500amol_25000amol" "00500amol_50000amol" "02500amol_05000amol"
#> [28] "02500amol_12500amol" "02500amol_25000amol" "02500amol_50000amol"
#> [31] "05000amol_12500amol" "05000amol_25000amol" "05000amol_50000amol"
#> [34] "12500amol_25000amol" "12500amol_50000amol" "25000amol_50000amol"
graphs[[1]][[3]]
#> IGRAPH 1b01676 UN-B 15 14 --
#> + attr: name (v/c), type (v/l), pep_logRatio (v/n)
#> + edges from 1b01676 (vertex names):
#> [1] sp|P09938|RIR2_YEAST--AEWALR
#> [2] sp|P09938|RIR2_YEAST--DEGLHTDFACLLFAHLK
#> [3] sp|P09938|RIR2_YEAST--DIHDWNNR
#> [4] sp|P09938|RIR2_YEAST--ELETLREENR
#> [5] sp|P09938|RIR2_YEAST--ESEFLFNAIHTIPEIGEK
#> [6] sp|P09938|RIR2_YEAST--IVTEAVEIEQR
#> [7] sp|P09938|RIR2_YEAST--LLVAFGNK
#> [8] sp|P09938|RIR2_YEAST--LLVAFGNKK
#> + ... omitted several edgesplotBipartiteGraph(graphs[[1]][[3]], node_labels_proteins = "accessions",
node_labels_peptides = "pep_logRatios")The optimization is performed independently on each graph. The
bipartite graph forms the basis of an equation system used to calculate
protein level ratios (\(R_i\)). The
graph combines information about the peptide ratios (\(r_j\)) and the proteins from which they can
originate. However, this is not enough to calculate them directly,
instead, a weight (\(C_i\)) is needed
for each protein. The optimization algorithm Rsolnp
(Galanos and Ye, 2025) is applied to the resulting equation system.
As an example we will use the following graph containing the proteins RL13A and RL13B.
plotBipartiteGraph(graphs[[1]][[1]], node_labels_proteins = "accessions",
node_labels_peptides = "pep_logRatios")The optimization process involves two steps. First, different combinations of protein weights are tested. In the second step, the best fitting (smallest error) \(C_i\) combination is extracted.
res <- iterateOverCi(graphs[[1]][[1]])
protQuant <- automatedAnalysisIteratedCi(graphs[[1]][[1]], res)Some of the results are not single values but a range of equally optimal solutions. This occurs if several combinations return the same error and the result is ambiguous. This can occur if peptide ratios are contradicting or the equation system is underdetermined.
The result is in a SummarizedExperiment object, and the
table can be accessed via the assays function.
head(assays(protQuant)$results)
#> graphID proteinNr error_min RiLog RiLog_min RiLog_max Ci
#> sp|P40212|RL13B_YEAST NA 1 7.06091 NA 0.5762211 0.5762325 NA
#> sp|Q12690|RL13A_YEAST NA 2 7.06091 NA -3.7837279 0.5058465 NA
#> Ci_min Ci_max case
#> sp|P40212|RL13B_YEAST 0.001 0.950 5
#> sp|Q12690|RL13A_YEAST 0.050 0.999 5In this example, the RiLog_min and
RiLog_max, as well as the Ci_min and
Ci_max can be seen. This is how the range results are
encoded. These values represent the boundaries of the log ratio and
range for the given error. The error_min shows how well the
calculated protein ratios fit the measured peptide ratios.
Considering the example graph, the reasons for the error value and ambiguity of the results are evident. The log(ratio) of the shared peptides ranges from -0.6 to 2.63, with a mean of around 0.55. The resulting variability explains the high margin of error. The log(ratio) of RL13B must be close to its unique peptide at 0.61. The size of the effect of RL13B on the shared peptides depends on the value of \(C_i\). Therefore, the log(ratio) of RL13A must adapt to this, creating the range of possibilities.
Results from the same comparison can be combined by using
rbind() on the quant results. However, running the
optimization for all the sample graphs takes too long for this
vignette.
The results from all the graphs can be combined into a single result.
Each comparison is treated as one assay in the final
SummarizedExperiment.
Please note that for simplicity, the comparisons in this example file are called “1_2”, “1_3” etc instead of using the spike-in concetration levels.
file <- system.file("extdata", "resultsList.rds", package = "bppg")
resultList <- readRDS(file)
SE <- combineComparisons(resultList)
SE
#> class: SummarizedExperiment
#> dim: 5 10
#> metadata(0):
#> assays(36): 1_2 1_3 ... 7_9 8_9
#> rownames(5): sp|P07262|DHE4_YEAST sp|P09938|RIR2_YEAST
#> sp|P39708|DHE5_YEAST sp|P40212|RL13B_YEAST sp|Q12690|RL13A_YEAST
#> rowData names(1): accession
#> colnames(10): graphID proteinNr ... Ci_max case
#> colData names(1): colnamesIt can also be exported to an Excel spreadsheet, with the assays on different sheets.
Although the single example was quick, processing a complete dataset
can take hours due to the large number of graphs involved. However,
optimization is applied to each graph individually, enabling easy
parallelization using tools such as batchtools (Lang,
Bischl, and Surmann, 2017), which supports HPC job scheduling. You can
see an example of this in the Nextflow workflow for this package: here.
#> ─ Session info ───────────────────────────────────────────────────────────────────────────────────────────────────────
#> setting value
#> version R version 4.6.1 (2026-06-24)
#> os Ubuntu 26.04.1 LTS
#> system x86_64, linux-gnu
#> ui X11
#> language (EN)
#> collate en_US.UTF-8
#> ctype en_US.UTF-8
#> tz Etc/UTC
#> date 2026-10-11
#> pandoc 3.8.3 @ /usr/local/bin/ (via rmarkdown)
#> quarto 1.9.37 @ /usr/local/bin/quarto
#>
#> ─ Packages ───────────────────────────────────────────────────────────────────────────────────────────────────────────
#> package * version date (UTC) lib source
#> abind 1.4-8 2024-09-12 [2] RSPM (R 4.6.0)
#> ade4 1.7-24 2026-03-21 [2] RSPM (R 4.6.0)
#> affy 1.91.0 2026-04-28 [2] https://bioc.r-universe.dev (R 4.6.1)
#> affyio 1.83.0 2026-04-28 [2] https://bioc.r-universe.dev (R 4.6.1)
#> backports 1.5.1 2026-04-03 [2] RSPM (R 4.6.0)
#> bibtex 0.5.3 2026-09-22 [2] RSPM (R 4.6.0)
#> Biobase * 2.73.2 2026-07-28 [2] https://bioc.r-universe.dev (R 4.6.1)
#> BiocGenerics * 0.59.12 2026-08-10 [2] https://bioc.r-universe.dev (R 4.6.1)
#> BiocManager 1.30.27 2025-11-14 [2] RSPM (R 4.6.0)
#> BiocStyle * 2.41.0 2026-04-28 [2] https://bioc.r-universe.dev (R 4.6.1)
#> bppg * 0.99.1 2026-08-12 [1] https://biocstaging.r-universe.dev (R 4.6.1)
#> bslib 0.12.0 2026-08-04 [2] RSPM (R 4.6.0)
#> buildtools 1.0.0 2026-10-10 [3] local (/pkg)
#> cachem 1.1.0 2024-05-16 [2] RSPM (R 4.6.0)
#> checkmate 2.3.4 2026-02-03 [2] RSPM (R 4.6.0)
#> cli 3.6.6 2026-04-09 [2] RSPM (R 4.6.0)
#> codetools 0.2-20 2024-03-31 [2] RSPM (R 4.6.0)
#> DelayedArray 0.39.8 2026-09-30 [2] https://bioc.r-universe.dev (R 4.6.1)
#> digest 0.6.39 2025-11-19 [2] RSPM (R 4.6.0)
#> dplyr 1.2.1 2026-04-03 [2] RSPM (R 4.6.0)
#> evaluate 1.0.5 2025-08-27 [2] RSPM (R 4.6.0)
#> farver 2.1.2 2024-05-13 [2] RSPM (R 4.6.0)
#> fastmap 1.2.0 2024-05-15 [2] RSPM (R 4.6.0)
#> future 1.76.0 2026-09-24 [2] RSPM (R 4.6.0)
#> future.apply 1.20.2 2026-02-20 [2] RSPM (R 4.6.0)
#> generics * 0.1.4 2025-05-09 [2] RSPM (R 4.6.0)
#> GenomicRanges * 1.65.4 2026-09-02 [2] https://bioc.r-universe.dev (R 4.6.1)
#> ggforce 0.5.0 2025-06-18 [2] RSPM (R 4.6.0)
#> ggplot2 4.0.3 2026-04-22 [2] RSPM (R 4.6.0)
#> ggraph 2.2.2 2025-08-24 [2] RSPM (R 4.6.0)
#> ggrepel 0.9.8 2026-03-17 [2] RSPM (R 4.6.0)
#> globals 0.19.1 2026-03-13 [2] RSPM (R 4.6.0)
#> glue 1.8.1 2026-04-17 [2] RSPM (R 4.6.0)
#> graphlayouts 1.2.5 2026-07-22 [2] RSPM (R 4.6.0)
#> gridExtra 2.3.1 2026-06-25 [2] RSPM (R 4.6.0)
#> gtable 0.3.6 2024-10-25 [2] RSPM (R 4.6.0)
#> htmltools 0.5.9 2025-12-04 [2] RSPM (R 4.6.0)
#> httr 1.4.9 2026-09-01 [2] RSPM (R 4.6.0)
#> igraph * 2.3.4 2026-09-30 [2] RSPM (R 4.6.0)
#> IRanges * 2.47.5 2026-08-27 [2] https://bioc.r-universe.dev (R 4.6.1)
#> jquerylib 0.1.4 2021-04-26 [2] RSPM (R 4.6.0)
#> jsonlite 2.0.0 2025-03-27 [2] RSPM (R 4.6.0)
#> knitr 1.52 2026-09-06 [2] RSPM (R 4.6.0)
#> labeling 0.4.3 2023-08-29 [2] RSPM (R 4.6.0)
#> lattice 0.23-1 2026-08-12 [2] RSPM (R 4.6.0)
#> lifecycle 1.0.5 2026-01-08 [2] RSPM (R 4.6.0)
#> limma 3.99.0 2026-08-30 [2] https://bioc.r-universe.dev (R 4.6.1)
#> listenv 1.1.0 2026-10-04 [2] RSPM (R 4.6.0)
#> lubridate 1.9.5 2026-02-04 [2] RSPM (R 4.6.0)
#> magrittr 2.0.5 2026-04-04 [2] RSPM (R 4.6.0)
#> maketools 1.3.2 2025-01-25 [3] RSPM (R 4.6.0)
#> MASS 7.3-66 2026-07-15 [2] RSPM (R 4.6.0)
#> Matrix 1.7-6 2026-07-25 [2] RSPM (R 4.6.0)
#> MatrixGenerics * 1.25.0 2026-04-28 [2] https://bioc.r-universe.dev (R 4.6.1)
#> matrixStats * 1.5.0 2025-01-07 [2] RSPM (R 4.6.0)
#> memoise 2.0.1 2021-11-26 [2] RSPM (R 4.6.0)
#> numDeriv 2016.8-1.1 2019-06-06 [2] RSPM (R 4.6.0)
#> openxlsx 4.2.9 2026-09-02 [2] RSPM (R 4.6.0)
#> otel 0.2.0 2025-08-29 [2] RSPM (R 4.6.0)
#> parallelly 1.48.0 2026-06-29 [2] RSPM (R 4.6.0)
#> pbapply 1.7-5 2026-09-01 [2] RSPM (R 4.6.0)
#> pillar 1.11.1 2025-09-17 [2] RSPM (R 4.6.0)
#> pkgconfig 2.0.3 2019-09-22 [2] RSPM (R 4.6.0)
#> plyr 1.8.9 2023-10-02 [2] RSPM (R 4.6.0)
#> polyclip 1.10-7 2024-07-23 [2] RSPM (R 4.6.0)
#> preprocessCore 1.75.1 2026-08-31 [2] https://bioc.r-universe.dev (R 4.6.1)
#> purrr 1.2.2 2026-04-10 [2] RSPM (R 4.6.0)
#> R6 2.6.1 2025-02-15 [2] RSPM (R 4.6.0)
#> RColorBrewer 1.1-3 2022-04-03 [2] RSPM (R 4.6.0)
#> Rcpp 1.1.2 2026-07-05 [2] RSPM (R 4.6.0)
#> RefManageR * 1.4.0 2022-09-30 [2] RSPM (R 4.6.0)
#> rlang 1.3.0 2026-07-05 [2] RSPM (R 4.6.0)
#> rmarkdown 2.32 2026-09-01 [2] RSPM (R 4.6.0)
#> Rsolnp 2.0.1 2025-06-30 [2] RSPM (R 4.6.0)
#> S4Arrays 1.13.2 2026-09-30 [2] https://bioc.r-universe.dev (R 4.6.1)
#> S4Vectors * 0.51.10 2026-09-15 [2] https://bioc.r-universe.dev (R 4.6.1)
#> S7 0.2.2 2026-04-22 [2] RSPM (R 4.6.0)
#> sass 0.4.10 2025-04-11 [2] RSPM (R 4.6.0)
#> scales 1.4.0 2025-04-24 [2] RSPM (R 4.6.0)
#> Seqinfo * 1.3.2 2026-08-26 [2] https://bioc.r-universe.dev (R 4.6.1)
#> seqinr * 4.2-44 2026-04-28 [2] RSPM (R 4.6.0)
#> sessioninfo * 1.2.4 2026-06-04 [2] RSPM (R 4.6.0)
#> SparseArray 1.13.4 2026-09-30 [2] https://bioc.r-universe.dev (R 4.6.1)
#> statmod 1.5.2 2026-05-17 [2] RSPM (R 4.6.0)
#> stringi 1.8.9 2026-08-04 [2] RSPM (R 4.6.0)
#> stringr 1.6.0 2025-11-04 [2] RSPM (R 4.6.0)
#> SummarizedExperiment * 1.43.0 2026-04-28 [2] https://bioc.r-universe.dev (R 4.6.1)
#> sys 3.4.3 2024-10-04 [2] RSPM (R 4.6.0)
#> tibble 3.3.1 2026-01-11 [2] RSPM (R 4.6.0)
#> tidygraph 1.3.1 2024-01-30 [2] RSPM (R 4.6.0)
#> tidyr 1.3.2 2025-12-19 [2] RSPM (R 4.6.0)
#> tidyselect 1.2.1 2024-03-11 [2] RSPM (R 4.6.0)
#> timechange 0.4.0 2026-01-29 [2] RSPM (R 4.6.0)
#> truncnorm 1.0-9 2023-03-20 [2] RSPM (R 4.6.0)
#> tweenr 2.0.3 2024-02-26 [2] RSPM (R 4.6.0)
#> vctrs 0.7.3 2026-04-11 [2] RSPM (R 4.6.0)
#> viridis 0.6.5 2024-01-29 [2] RSPM (R 4.6.0)
#> viridisLite 0.4.3 2026-02-04 [2] RSPM (R 4.6.0)
#> vsn 3.81.1 2026-09-23 [2] https://bioc.r-universe.dev (R 4.6.1)
#> withr 3.0.3 2026-06-19 [2] RSPM (R 4.6.0)
#> xfun 0.61 2026-09-16 [2] RSPM (R 4.6.0)
#> xml2 1.6.0 2026-06-22 [2] RSPM (R 4.6.0)
#> XVector 0.53.0 2026-04-28 [2] https://bioc.r-universe.dev (R 4.6.1)
#> yaml 2.3.12 2025-12-10 [2] RSPM (R 4.6.0)
#> zip 3.0.2 2026-08-04 [2] RSPM (R 4.6.0)
#>
#> [1] /tmp/Rtmphvspau/Rinst1880597ca4cf
#> [2] /github/workspace/pkglib
#> [3] /usr/local/lib/R/site-library
#> [4] /usr/lib/R/site-library
#> [5] /usr/lib/R/library
#> * ── Packages attached to the search path.
#>
#> ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
This vignette was generated using BiocStyle with knitr and rmarkdown (Allaire, Xie, Dervieux, McPherson, Luraschi, Ushey, Atkins, Wickham, Cheng, Chang, and Iannone, 2026) running behind the scenes.
Citations made with RefManageR (McLean, 2017).
Allaire, J., Y. Xie, et al. (2026). rmarkdown: Dynamic Documents for R. R package version 2.32. URL: https://github.com/rstudio/rmarkdown.
Galanos, A. and Y. Ye (2025). Rsolnp: General Non-Linear Optimization. R package version 2.0.1.
Lang, M., B. Bischl, et al. (2017). “batchtools: Tools for R to work on batch systems”. In: The Journal of Open Source Software. DOI: 10.21105/joss.00135. URL: https://doi.org/10.21105/joss.00135.
McLean, M. W. (2017). “RefManageR: Import and Manage BibTeX and BibLaTeX References in R”. In: The Journal of Open Source Software. DOI: 10.21105/joss.00338.
Ramus, C., A. Hovasse, et al. (2016). “Spiked proteomic standard dataset for testing label-free quantitative software and statistical methods”. In: Data in Brief 6, pp. 286–294. ISSN: 2352-3409. DOI: 10.1016/j.dib.2015.11.063. URL: https://www.sciencedirect.com/science/article/pii/S2352340915003601 (visited on Mar. 21, 2025).
Schork, K. (2024). “Improvement of protein quantification for proteins with shared peptides by using bipartite peptide-protein graphs”. DOI: http://dx.doi.org/10.17877/DE290R-25361.
Schork, K., J. Wenzel, et al. (2026). bppg: Bipartite peptide-protein graphs. URL: https://github.com/mpc-bioinformatics/bppg.