Skip to contents

Model overview

score_peptides() reduces a digest tibble to one row per protein. That row contains component scores, a composite score, a verdict, and the digest-level median_peptide_length used to interpret peptide density.

The model uses explicit component scores and a weighted sum so that each contribution remains visible.

Positioning

pepVet is not a peptide detectability predictor. It does not estimate whether an experiment will identify a specific peptide from empirical MS training data. Instead, it ranks a protein digest for a chosen enzyme-workflow combination.

  • ML detectability models learn nonlinear interactions from observed peptide detections.
  • pepVet uses a rule-based multi-criteria decision analysis with explicit, linear weights.
  • ML detectability models output per-peptide predictions or suitability scores, depending on the model.
  • pepVet outputs per-protein digest-quality rankings.

Interpret pepVet as a digest-ranking model for pre-acquisition planning, not as a substitute for peptide-level detectability prediction.

Valid peptides

Most pepVet components operate on valid peptides. A peptide is valid if its length falls inside the active length_range.

The default window is 7 to 25 residues. It is a strict, conservative prior for routine workflows, not a universal LC-MS/MS detection boundary.

v(p)=𝟏{7|p|25} v(p) = \mathbf{1}\{7 \le |p| \le 25\}

Peptides outside that window still appear in digest_protein() output. They are real cleavage products, but the default score excludes them from its valid-peptide numerators. Empirical work shows that peptide observability depends on physicochemical properties and the analytical platform rather than on one universal length interval (Mallick et al. 2007). Use a preset or custom range when the workflow supports different boundaries.

short_seq <- "AKAKAKAKAKAKAKAKAKAKAKAKAKAKAKAKAK"
evaluate_digest(short_seq, enzyme = "trypsin")$scores
#> # A tibble: 1 × 12
#>   protein_id S_length S_coverage S_count S_hydro S_charge composite_score
#>   <chr>         <dbl>      <dbl>   <dbl>   <dbl>    <dbl>           <dbl>
#> 1 sequence_1        0          0       0       0        0               0
#> # ℹ 5 more variables: verdict <chr>, median_peptide_length <dbl>,
#> #   preset_used <chr>, n_high_efficiency_sites <int>,
#> #   n_low_efficiency_sites <int>

Component scores

S_length

S_length is the fraction of peptides that are valid.

Slength=NvalidNtotal S_{length} = \frac{N_{valid}}{N_{total}}

Low S_length can result from many products below the active window or from long products above it.

S_coverage

S_coverage is the fraction of the protein sequence covered by at least one valid peptide.

Scoverage=RcoveredL S_{coverage} = \frac{R_{covered}}{L}

pepVet merges overlapping valid peptide intervals before summing widths. A residue covered twice still counts once.

S_count

S_count is a normalized peptide-density score.

In the current release, the expected peptide density is enzyme-aware. For digests with at least three peptide rows, pepVet uses the observed digest median length. For sparse digests, it falls back to enzyme-class expectations.

Nexpected=LM N_{expected} = \frac{L}{M}

Scount=min(NvalidNexpected,1) S_{count} = \min\left(\frac{N_{valid}}{N_{expected}}, 1\right)

This is a bounded heuristic, not a mechanistic cleavage model. Enzyme-aware medians keep tryptic and GluC digests from sharing one fixed peptide-density prior.

ev_bsa <- evaluate_digest(bsa_path, enzyme = "trypsin", missed_cleavages = 1L)
ev_bsa$scores[, c("S_count", "median_peptide_length", "composite_score")]
#> # A tibble: 1 × 3
#>   S_count median_peptide_length composite_score
#>     <dbl>                 <dbl>           <dbl>
#> 1       1                    10           0.885

When there are no cleavage sites for the selected enzyme, pepVet warns and sets S_count to 0. A zero S_count is a failed digest, so pepVet also sets the composite score to 0 and the verdict to Poor. This hard failure applies even when the uncut full-length peptide falls inside the active length window and gives full sequence coverage. It is the documented exception to the weighted-sum equation.

S_hydro

S_hydro is the fraction of valid peptides with GRAVY values inside the active gravy_range.

G(p)=1|p|iKDi G(p) = \frac{1}{|p|}\sum_i KD_i

Shydro=NwindowNvalid S_{hydro} = \frac{N_{window}}{N_{valid}}

The default range is -1.0 to 0.6. The membrane preset assumes a wider hydrophobicity range and extends the upper boundary to 2.0.

S_charge

S_charge is the fraction of valid peptides that retain at least one non-terminal basic residue.

Schargerichness=NbasicNvalid S_{\mathrm{charge\,richness}} = \frac{N_{basic}}{N_{valid}}

This score does not predict ionization or fragmentation. The implementation uses non-terminal basic residues as a charge-richness proxy. A value of zero means that no valid peptide contains such a residue.

S_unique

S_unique requires a supplied proteome digest.

Sunique=NuniqueNvalid S_{unique} = \frac{N_{unique}}{N_{valid}}

This score describes uniqueness against the supplied proteome digest. Without that background, pepVet cannot calculate the component and omits it.

Composite score and verdicts

The component scores enter a weighted sum, which the package then maps to one of three advisory labels.

Weights and presets

The composite score is a weighted sum.

C=iwiSi,iwi=1 C = \sum_i w_i S_i, \qquad \sum_i w_i = 1

Default weights depend on whether S_unique is in play.

Mode Weight vector
Protein-only c(S_length = 0.200, S_coverage = 0.348, S_count = 0.226, S_hydro = 0.138, S_charge = 0.088)
Proteome-aware c(S_length = 0.160, S_coverage = 0.279, S_count = 0.181, S_hydro = 0.110, S_charge = 0.070, S_unique = 0.200)

Default weights are documented expert priors that encode relative importance chosen for pepVet. They were not fitted to experimental outcomes, and the repository does not retain a derivation record that supports a more specific provenance claim. Coverage and peptide count receive the largest combined weight in the protein-only vector.

pepvet_preset() returns shipped starting configurations for several workflows.

pepvet_preset("dia")
#> $gravy_range
#> [1] -1.0  0.8
#> 
#> $length_range
#> [1]  7 30
#> 
#> $weights
#>   S_length S_coverage    S_count    S_hydro   S_charge   S_unique 
#>        0.2        0.3        0.2        0.1        0.1        0.1 
#> 
#> $include_pI
#> [1] FALSE
pepvet_preset("membrane")
#> $gravy_range
#> [1] -1  2
#> 
#> $length_range
#> [1]  7 30
#> 
#> $weights
#>   S_length S_coverage    S_count    S_hydro   S_charge   S_unique 
#>       0.25       0.25       0.20       0.05       0.15       0.10 
#> 
#> $include_pI
#> [1] FALSE

These presets record four settings together.

  • length_range
  • gravy_range
  • weights
  • include_pI

Changing a preset can alter both the weights and the peptide windows. Inspect the resolved values before comparing scores.

score_peptides() records the resolved configuration in preset_used. When the active GRAVY range, peptide-length range, weights, and pI flag exactly match a shipped preset, the function reports the preset name. Otherwise it reports "custom". Use this field to identify scores produced under different workflow assumptions.

Verdict thresholds

pepVet maps the composite score to three labels.

Verdict Threshold
Good >= 0.65
Moderate >= 0.40
Poor < 0.40

The package retains these strict, conservative thresholds as triage boundaries. No analysis has calibrated them to an identification probability, false discovery rate, or fixed instrument platform. The current PeptideAtlas analysis contained too few negative protein-level examples for reliable calibration. Use the labels for ranking and review, not as experimental outcome claims.

Worked outputs

digest_report(evaluate_digest(bsa_path, enzyme = "trypsin", missed_cleavages = 1L))
#> pepVet digest check
#> -------------------
#> Protein            sp|P02769|ALBU_BOVIN Albumin OS=Bos taurus OX=9913 GN=ALB
#>                    PE=1 SV=4
#> Enzyme             trypsin
#> Preset             standard
#> Missed cleavages   Up to 1
#> Peptides           157 total; 108 within 7-25 aa
#> Verdict            Good
#> Composite          0.885
#> Component        Score  Profile
#> S_length         0.688  [#######---]
#> S_coverage       0.997  [##########]
#> S_count          1.000  [##########]
#> S_hydro          0.769  [########--]
#> S_charge         0.778  [########--]
digest_report(evaluate_digest(h3_path, enzyme = "trypsin"))
#> pepVet digest check
#> -------------------
#> Protein            sp|P68431|H31_HUMAN Histone H3.1 OS=Homo sapiens OX=9606
#>                    GN=H3C1 PE=1 SV=2
#> Enzyme             trypsin
#> Preset             standard
#> Missed cleavages   Up to 1
#> Peptides           59 total; 18 within 7-25 aa
#> Verdict            Moderate
#> Composite          0.619
#> Component        Score  Profile
#> S_length         0.305  [###-------]
#> S_coverage       0.632  [######----]
#> S_count          0.662  [#######---]
#> S_hydro          0.833  [########--]
#> S_charge         0.833  [########--]

The two reports show the component values for BSA and H3.1 under the specified trypsin settings. Interpret the displayed values rather than treating either protein as a universal positive or negative control.

Interpretation boundaries

The model is intended for within-configuration digest ranking. Its limits and the available empirical checks define how far that interpretation can go.

Limitations

The current model has several limits.

  • It does not model post-translational modifications directly.
  • It does not model chromatographic gradients, charge-state envelopes, or instrument-specific fragmentation methods.
  • It uses heuristic windows and thresholds rather than empirically calibrated identification probabilities.
  • It assumes the supplied proteome digest is the relevant comparison space for uniqueness.
  • It assumes the active GRAVY and length windows describe a conventional C18 reversed-phase LC with ESI unless a different preset or custom configuration is supplied.
  • It treats the weight vectors as expert priors, not validated coefficients.

These limits define the intended use: digest planning, enzyme ranking, and pre-acquisition triage under an explicit scoring configuration.

Scope

pepVet scores are rankings, not calibrated probabilities. The composite score has no unit. Comparisons should remain within one enzyme-workflow configuration.

Cross-preset comparisons are not valid just because the numeric scale looks the same. A standard score of 0.75 and a targeted score of 0.60 reflect different weight vectors and can answer different questions.

Empirical evaluation

A January 2026 analysis evaluated the default parameters against a human PeptideAtlas build containing 5.3 million unique observed peptide sequences. Internal score diagnostics also described component relationships. These analyses provide evidence about the sampled data and model behavior, but they do not establish performance across organisms, enzymes, instruments, or workflows.

  • Score diagnostics (score_diagnostics()): VIF, PCA, and ablation describe component relationships and the effect of removing each component in the evaluated sample. See the Score Diagnostics article.

  • PeptideAtlas concordance: in the sampled human tryptic digests, the mean observation rate was 38.0 percentage points higher for peptides inside the default length and GRAVY windows than for peptides outside them (bootstrap 95% CI [36.1, 40.0] percentage points). Wider grid-search ranges produced greater enrichment, which is consistent with the defaults acting as strict, conservative filters rather than estimated detection boundaries. See the PeptideAtlas Concordance article for the analysis and its limitations.

References

Mallick P, Schirle M, Chen SS, et al. Computational prediction of proteotypic peptides for quantitative proteomics. Nature Biotechnology. 2007;25:125-131. doi: 10.1038/nbt1275.

Session info

sessionInfo()
#> R version 4.6.1 (2026-06-24)
#> Platform: x86_64-pc-linux-gnu
#> Running under: Ubuntu 24.04.4 LTS
#> 
#> Matrix products: default
#> BLAS:   /usr/lib/x86_64-linux-gnu/openblas-pthread/libblas.so.3 
#> LAPACK: /usr/lib/x86_64-linux-gnu/openblas-pthread/libopenblasp-r0.3.26.so;  LAPACK version 3.12.0
#> 
#> locale:
#>  [1] LC_CTYPE=C.UTF-8       LC_NUMERIC=C           LC_TIME=C.UTF-8       
#>  [4] LC_COLLATE=C.UTF-8     LC_MONETARY=C.UTF-8    LC_MESSAGES=C.UTF-8   
#>  [7] LC_PAPER=C.UTF-8       LC_NAME=C              LC_ADDRESS=C          
#> [10] LC_TELEPHONE=C         LC_MEASUREMENT=C.UTF-8 LC_IDENTIFICATION=C   
#> 
#> time zone: UTC
#> tzcode source: system (glibc)
#> 
#> attached base packages:
#> [1] stats     graphics  grDevices utils     datasets  methods   base     
#> 
#> other attached packages:
#> [1] pepVet_0.99.1
#> 
#> loaded via a namespace (and not attached):
#>  [1] vctrs_0.7.3          crayon_1.5.3         cli_3.6.6           
#>  [4] knitr_1.51           rlang_1.3.0          xfun_0.60           
#>  [7] otel_0.2.0           generics_0.1.4       textshaping_1.0.5   
#> [10] jsonlite_2.0.0       glue_1.8.1           S4Vectors_0.51.5    
#> [13] Biostrings_2.81.5    htmltools_0.5.9      stats4_4.6.1        
#> [16] ragg_1.5.2           sass_0.4.10          cleaver_1.51.0      
#> [19] rmarkdown_2.31       Seqinfo_1.3.0        tibble_3.3.1        
#> [22] evaluate_1.0.5       jquerylib_0.1.4      fastmap_1.2.0       
#> [25] IRanges_2.47.2       yaml_2.3.12          lifecycle_1.0.5     
#> [28] compiler_4.6.1       fs_2.1.0             pkgconfig_2.0.3     
#> [31] XVector_0.53.0       systemfonts_1.3.2    digest_0.6.39       
#> [34] R6_2.6.1             utf8_1.2.6           pillar_1.11.1       
#> [37] magrittr_2.0.5       bslib_0.11.0         tools_4.6.1         
#> [40] pkgdown_2.2.1        BiocGenerics_0.59.10 cachem_1.1.0        
#> [43] desc_1.4.3