Getting Started with pepVet

pepVet evaluates proteolytic digests before acquisition. A protein sequence and enzyme produce peptide coordinates, score components, a composite label, and the resolved scoring parameters. The tool comparison describes differences between pepVet and five other digestion tools.

The core pipeline

Protein sequence
      |
      v
    digest_protein()    ->  tibble of peptides (one row per peptide)
      |
      v
    score_peptides()    ->  one-row tibble of component scores + verdict
      |
      v
    evaluate_digest()   ->  convenience wrapper: digest + score + params in one call
      |
      v
    pepvet_check()      ->  evaluate + print report in one interactive call
      |
      v
    compare_digests()   ->  run evaluate_digest across N enzymes, rank by composite
      |
      v
    recommend_enzyme()  ->  return the name of the top-ranked enzyme
      |
      v
    batch_evaluate()    ->  run evaluate_digest across all proteins in a FASTA
      |                     returns a flat tibble: one row per protein
      v
    summarize_batch()   ->  proteome-level verdict distribution and score stats
      |
      v
    triage_proteins()   ->  per-protein action labels
      |
      v
    export_peptide_list()  ->  export valid peptides to Skyline, generic CSV, or FASTA
      |
      v
    digest_report()     ->  compact console output for any of the above

Every output is programmatic. digest_protein() returns a tibble with one row per peptide. score_peptides() returns a tibble with one row per protein. compare_digests() returns a tibble with one row per enzyme. evaluate_digest() returns a named list with the score tibble, the peptide tibble, and the resolved parameters.

Protein input

Every pepVet function that takes a protein sequence accepts the same input shapes. You can pass:

  • a raw character sequence
  • a named character vector (one entry per protein)
  • a Biostrings::AAString or AAStringSet
  • a path to a FASTA file (single- or multi-entry)

The package ships fixed FASTA fixtures in inst/extdata/ for these examples.

bsa_path <- system.file("extdata", "P02769.fasta", package = "pepVet")
h3_path <- system.file("extdata", "P68431.fasta", package = "pepVet")
proteome_path <- system.file(
  "extdata", "small_proteome_50_proteins.fasta",
  package = "pepVet"
)

Step 1: Digest a protein

digest_protein() cleaves a protein sequence using any cleaver-compatible enzyme rule and returns a tibble with one row per peptide fragment.

digest_protein(bsa_path, enzyme = "trypsin", missed_cleavages = 1L)
#> # A tibble: 157 × 6
#>    protein_id                        peptide start   end length missed_cleavages
#>    <chr>                             <chr>   <int> <int>  <int>            <int>
#>  1 sp|P02769|ALBU_BOVIN Albumin OS=… MK          1     2      2                0
#>  2 sp|P02769|ALBU_BOVIN Albumin OS=… MKWVTF…     1    19     19                1
#>  3 sp|P02769|ALBU_BOVIN Albumin OS=… WVTFIS…     3    19     17                0
#>  4 sp|P02769|ALBU_BOVIN Albumin OS=… WVTFIS…     3    23     21                1
#>  5 sp|P02769|ALBU_BOVIN Albumin OS=… GVFR       20    23      4                0
#>  6 sp|P02769|ALBU_BOVIN Albumin OS=… GVFRR      20    24      5                1
#>  7 sp|P02769|ALBU_BOVIN Albumin OS=… R          24    24      1                0
#>  8 sp|P02769|ALBU_BOVIN Albumin OS=… RDTHK      24    28      5                1
#>  9 sp|P02769|ALBU_BOVIN Albumin OS=… DTHK       25    28      4                0
#> 10 sp|P02769|ALBU_BOVIN Albumin OS=… DTHKSE…    25    34     10                1
#> # ℹ 147 more rows

The output columns are:

Column Description
protein_id Full FASTA header or supplied name
peptide Amino acid sequence of the fragment
start 1-based start position in the parent protein
end 1-based end position (inclusive)
length Peptide length in residues
missed_cleavages Number of internal cleavage sites skipped

digest_protein() expands missed cleavages explicitly and retains exact start and end coordinates for each joined product.

# mc=0: strict cleavage only
digest_protein("AKRTPK", enzyme = "trypsin", missed_cleavages = 0L)
#> # A tibble: 3 × 6
#>   protein_id peptide start   end length missed_cleavages
#>   <chr>      <chr>   <int> <int>  <int>            <int>
#> 1 sequence_1 AK          1     2      2                0
#> 2 sequence_1 R           3     3      1                0
#> 3 sequence_1 TPK         4     6      3                0

# mc=1: also include once-skipped joins
digest_protein("AKRTPK", enzyme = "trypsin", missed_cleavages = 1L)
#> # A tibble: 5 × 6
#>   protein_id peptide start   end length missed_cleavages
#>   <chr>      <chr>   <int> <int>  <int>            <int>
#> 1 sequence_1 AK          1     2      2                0
#> 2 sequence_1 AKR         1     3      3                1
#> 3 sequence_1 R           3     3      1                0
#> 4 sequence_1 RTPK        3     6      4                1
#> 5 sequence_1 TPK         4     6      3                0

The validation layer checks enzyme names against a registry of 40 cleaver-compatible rules, normalises case, and trims whitespace. Common examples include trypsin, lysc, glutamyl endopeptidase, asp-n endopeptidase, chymotrypsin-high, and thermolysin. The input " Trypsin " therefore resolves to trypsin.

Step 1a: Inspect cleavage efficiency

annotate_cleavage_sites() classifies local trypsin-family motifs using the package’s sequence rules.

annotate_cleavage_sites(bsa_path, enzyme = "trypsin")
#> # A tibble: 86 × 5
#>    position residue flanking_context efficiency rule_applied           
#>       <int> <chr>   <chr>            <chr>      <chr>                  
#>  1        2 K       MKWV             high       default_trypsin_site   
#>  2       19 R       YSRGV            high       default_trypsin_site   
#>  3       23 R       VFRRD            medium     adjacent_basic_residues
#>  4       24 R       FRRDT            low        acidic_p1_prime        
#>  5       28 K       THKSE            high       default_trypsin_site   
#>  6       34 R       AHRFK            high       default_trypsin_site   
#>  7       36 K       RFKDL            low        acidic_p1_prime        
#>  8       44 K       HFKGL            high       default_trypsin_site   
#>  9       65 K       HVKLV            high       default_trypsin_site   
#> 10       75 K       FAKTC            high       default_trypsin_site   
#> # ℹ 76 more rows

pepVet currently labels tryptic sites as:

  • low for proline-blocked (KP / RP) and acidic P1’ (KD, KE, RD, RE) motifs
  • medium for adjacent-basic sites such as KK, KR, and RR
  • high for other tryptic sites

These labels are sequence-local annotations. They do not model structure, PTMs, extended subsite preferences, cleavage probability, or abundance.

Step 2: Score the peptide set

score_peptides() summarises a digest tibble into per-protein component scores and a weighted composite verdict.

digest_result <- digest_protein(bsa_path,
  enzyme = "trypsin",
  missed_cleavages = 1L
)
score_peptides(digest_result)
#> # A tibble: 1 × 10
#>   protein_id        S_length S_coverage S_count S_hydro S_charge composite_score
#>   <chr>                <dbl>      <dbl>   <dbl>   <dbl>    <dbl>           <dbl>
#> 1 sp|P02769|ALBU_B…    0.688      0.997       1   0.769    0.778           0.885
#> # ℹ 3 more variables: verdict <chr>, median_peptide_length <dbl>,
#> #   preset_used <chr>

Only peptides inside the active length_range count as valid. The default window is 7 to 25 residues. Fragments outside that window still appear in the digest tibble, but they do not contribute to the component numerators. See the scoring model article for the formula of each component.

Composite score verdict thresholds are Good at >= 0.65, Moderate at >= 0.40, and Poor below 0.40. These strict, conservative boundaries are package design choices for triage. They are not calibrated probabilities, and the current PeptideAtlas analysis did not reliably calibrate them. Treat the labels as prompts for review, not predictions of experimental success.

Scoring model

pepVet is not a peptide detectability predictor. Existing ML-based tools learn peptide-level detection patterns from experimental MS data. pepVet does something narrower: it ranks the digest quality of a protein for a chosen enzyme-workflow combination using explicit physicochemical criteria.

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

pepVet scores describe which digest-level components raise or lower a ranking. They do not estimate the observation probability of a specific peptide.

The scoring model separates package design choices, expert priors, physical constants, and the limited PeptideAtlas evaluation. The workflow presets article lists the resolved settings for each preset.

Known limitations

  • Verdict thresholds are heuristic labels, not calibrated classifications.
  • Weight vectors are expert priors, not empirically trained coefficients.
  • The model omits PTMs, chemical labels, and digestion chemistry beyond the current rules.
  • GRAVY and peptide-length windows assume conventional C18 reversed-phase LC with ESI.
  • S_charge reflects extra internal basic-residue richness, not whether a peptide can ionize at all.
  • Proteome-aware uniqueness is only as relevant as the proteome digest you supply.

Scope

pepVet scores are interpretable rankings, not calibrated probabilities. The composite score has no unit. It ranks proteins by digest quality within a given enzyme-workflow combination.

Cross-workflow comparisons are not valid when the resolved scoring configuration changes. score_peptides() records a preset_used column. The function reports a preset name when the resolved GRAVY window, peptide-length window, weights, and pI setting exactly match a shipped preset. It marks other configurations as "custom".

Step 2a: Apply a workflow preset

Workflow presets give you a starting parameter set for common experiment types. Each preset returns a list with gravy_range, length_range, and weights, so you can pass the result into evaluate_digest() or score_peptides() directly.

pepvet_preset("standard")
#> $gravy_range
#> [1] -1.0  0.6
#> 
#> $length_range
#> [1]  7 25
#> 
#> $weights
#>   S_length S_coverage    S_count    S_hydro   S_charge   S_unique 
#>      0.200      0.348      0.226      0.138      0.088      0.000 
#> 
#> $include_pI
#> [1] FALSE
syn_path <- system.file("extdata", "P37840_isoforms.fasta", package = "pepVet")
syn_proteome <- digest_protein(syn_path, enzyme = "trypsin")
targeted_preset <- pepvet_preset("targeted")

do.call(
  evaluate_digest,
  c(list(sequence = syn_path, enzyme = "trypsin", proteome = syn_proteome), targeted_preset)
)$scores
#> # A tibble: 3 × 13
#>   protein_id               S_length S_coverage S_count S_hydro S_charge S_unique
#>   <chr>                       <dbl>      <dbl>   <dbl>   <dbl>    <dbl>    <dbl>
#> 1 sp|P37840|SYUA_HUMAN Al…    0.516      0.693       1   0.812    0.688    0    
#> 2 sp|P37840-2|SYUA_HUMAN …    0.581      1           1   0.722    0.667    0.111
#> 3 sp|P37840-3|SYUA_HUMAN …    0.481      0.659       1   0.692    0.615    0.231
#> # ℹ 6 more variables: composite_score <dbl>, verdict <chr>,
#> #   median_peptide_length <dbl>, preset_used <chr>,
#> #   n_high_efficiency_sites <int>, n_low_efficiency_sites <int>

Six presets ship with pepVet. Each bundles a length range, a GRAVY window, and scoring weights for a common experiment type. See the workflow presets article for the full reference.

Presets with non-zero S_unique weights require a proteome digest. pepVet rejects those presets when proteome is missing because the component is undefined without a comparison background.

Step 2b: Add proteome-aware uniqueness

When you supply a proteome digest, score_peptides() adds a sixth component, S_unique. It measures the fraction of valid peptides that appear in exactly one protein in the supplied background. Shared sequences can map to more than one protein, so the relevance of this component depends on the background.

# Digest the proteome background first
proteome_digest <- digest_protein(proteome_path, enzyme = "trypsin")

# Score BSA in the context of that proteome
bsa_digest <- digest_protein(bsa_path, enzyme = "trypsin")
score_peptides(bsa_digest, proteome = proteome_digest)

Proteome-aware scoring switches the default weight set to give S_unique a 20% share: 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).

Step 3: Evaluate in one call

evaluate_digest() wraps digest_protein() and score_peptides() into a single call and returns a named list.

ev <- evaluate_digest(bsa_path, enzyme = "trypsin", missed_cleavages = 1L)
names(ev)
#> [1] "scores"   "peptides" "params"
ev$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 sp|P02769|ALBU_B…    0.688      0.997       1   0.769    0.778           0.885
#> # ℹ 5 more variables: verdict <chr>, median_peptide_length <dbl>,
#> #   preset_used <chr>, n_high_efficiency_sites <int>,
#> #   n_low_efficiency_sites <int>
ev$params
#> $enzyme
#> [1] "trypsin"
#> 
#> $missed_cleavages
#> [1] 1
#> 
#> $protein_ids
#> [1] "sp|P02769|ALBU_BOVIN Albumin OS=Bos taurus OX=9913 GN=ALB PE=1 SV=4"
#> 
#> $preset_used
#> [1] "standard"
#> 
#> $gravy_range
#> [1] -1.0  0.6
#> 
#> $length_range
#> [1]  7 25
#> 
#> $weights
#>   S_length S_coverage    S_count    S_hydro   S_charge 
#>      0.200      0.348      0.226      0.138      0.088 
#> 
#> $proteome_aware
#> [1] FALSE
#> 
#> $include_pI
#> [1] FALSE

The $params element records the resolved enzyme name, missed cleavages, full protein IDs, and preset_used value.

When you need peptide-level cleavage-risk context, request it explicitly. The flag adds a cleavage_efficiency column to the peptide table. The protein-level efficiency counts (n_high_efficiency_sites, n_low_efficiency_sites) are always present in the scores table regardless of this flag.

ev_eff <- evaluate_digest(
  bsa_path,
  enzyme = "trypsin",
  missed_cleavages = 1L,
  include_cleavage_efficiency = TRUE
)

ev_eff$peptides
#> # A tibble: 157 × 7
#>    protein_id    peptide start   end length missed_cleavages cleavage_efficiency
#>    <chr>         <chr>   <int> <int>  <int>            <int> <chr>              
#>  1 sp|P02769|AL… MK          1     2      2                0 high               
#>  2 sp|P02769|AL… MKWVTF…     1    19     19                1 high               
#>  3 sp|P02769|AL… WVTFIS…     3    19     17                0 high               
#>  4 sp|P02769|AL… WVTFIS…     3    23     21                1 medium             
#>  5 sp|P02769|AL… GVFR       20    23      4                0 medium             
#>  6 sp|P02769|AL… GVFRR      20    24      5                1 low                
#>  7 sp|P02769|AL… R          24    24      1                0 low                
#>  8 sp|P02769|AL… RDTHK      24    28      5                1 low                
#>  9 sp|P02769|AL… DTHK       25    28      4                0 low                
#> 10 sp|P02769|AL… DTHKSE…    25    34     10                1 low                
#> # ℹ 147 more rows
ev_eff$scores[, c("protein_id", "n_high_efficiency_sites", "n_low_efficiency_sites")]
#> # A tibble: 1 × 3
#>   protein_id                       n_high_efficiency_si…¹ n_low_efficiency_sites
#>   <chr>                                             <int>                  <int>
#> 1 sp|P02769|ALBU_BOVIN Albumin OS…                     61                     18
#> # ℹ abbreviated name: ¹​n_high_efficiency_sites

The protein-level counts are informational and do not contribute to the score. They summarize the sequence-local labels returned by the annotation rules.

Step 4: Compare enzymes

compare_digests() runs evaluate_digest() across a vector of enzyme names for a single protein and returns a tibble sorted from best to worst composite score.

comp <- compare_digests(
  bsa_path,
  enzymes = c(
    "trypsin", "lysc", "glutamyl endopeptidase",
    "asp-n endopeptidase", "chymotrypsin-high"
  ),
  missed_cleavages = 1L
)
comp
#> # A tibble: 5 × 13
#>   enzyme protein_id S_length S_coverage S_count S_hydro S_charge composite_score
#>   <chr>  <chr>         <dbl>      <dbl>   <dbl>   <dbl>    <dbl>           <dbl>
#> 1 tryps… sp|P02769…    0.688      0.997   1       0.769    0.778           0.885
#> 2 gluta… sp|P02769…    0.681      0.936   1       0.802    0.975           0.884
#> 3 lysc   sp|P02769…    0.628      0.857   1       0.763    0.776           0.823
#> 4 asp-n… sp|P02769…    0.494      0.529   0.923   0.725    0.925           0.673
#> 5 chymo… sp|P02769…    0.477      0.590   0.840   0.549    0.863           0.642
#> # ℹ 5 more variables: verdict <chr>, median_peptide_length <dbl>,
#> #   preset_used <chr>, n_high_efficiency_sites <int>,
#> #   n_low_efficiency_sites <int>

compare_digests() defines one row per enzyme for one protein and therefore rejects multi-protein input.

Step 5: Get the top model rank

recommend_enzyme() runs compare_digests() internally and returns the name of the highest-scoring enzyme as a character string. If multiple enzymes tie on the composite score, the function returns all tied names in alphabetical order. Despite the function’s established name, this is a model ranking under the supplied settings, not an experimental recommendation.

recommend_enzyme(
  bsa_path,
  enzymes = c(
    "trypsin", "lysc", "glutamyl endopeptidase",
    "asp-n endopeptidase", "chymotrypsin-high"
  ),
  missed_cleavages = 1L
)
#> [1] "trypsin"

Step 6: Batch across a proteome

batch_evaluate() runs evaluate_digest() independently for every protein in a multi-FASTA file and returns a flat tibble with one row per protein. Columns include protein_id, protein_length, all component scores, composite_score, verdict, count fields, and four sequence-level difficulty flags.

batch <- batch_evaluate(proteome_path,
  enzyme = "trypsin",
  missed_cleavages = 1L
)

# Number of proteins evaluated
nrow(batch)

# Score and verdict for the first few proteins
batch[, c("protein_id", "composite_score", "verdict")]

batch_evaluate() evaluates each protein independently. Valid-peptide counts and hydrophobicity flags follow the active length_range and gravy_range. Short-protein and low-complexity flags remain fixed sequence-level heuristics. The returned tibble serves as input to summarize_batch() and triage_proteins().

For proteome-aware uniqueness scoring, supply a background proteome digest:

proteome_digest <- digest_protein(proteome_path, enzyme = "trypsin")
batch <- batch_evaluate(proteome_path,
  enzyme = "trypsin",
  proteome = proteome_digest
)

Step 6a: Summarize a batch

summarize_batch() computes proteome-level aggregate statistics from the tibble returned by batch_evaluate(). It returns a named list with five elements.

summary <- summarize_batch(batch)

# Verdict distribution (Good / Moderate / Poor and their percentages)
summary$verdict_counts

# Composite score distribution
summary$score_distribution

# Per-component mean scores: lowest value is the weakest dimension
summary$component_summary

# Proteins in the bottom 10% by composite score
summary$problem_proteins

# Moderate / Poor proteins where hydrophobicity or short-protein flags are set:
# likely candidates for switching to a less specific enzyme
summary$enzyme_switch_candidates

enzyme_switch_candidates is a heuristic derived from sequence-level difficulty flags, not from running alternative enzymes. Use compare_digests() to assess a specific alternative enzyme under the active scoring settings.

Step 6b: Triage proteins

triage_proteins() appends a deterministic action label derived from the verdict and difficulty flags.

triaged <- triage_proteins(batch)

# Count of each action
table(triaged$action)

# Proteins that should be tried with a different enzyme
triaged[
  triaged$action == "try_other_enzyme",
  c("protein_id", "verdict", "composite_score")
]

The action rules are:

  • proceed: the verdict is Good.
  • skip: a non-Good row has no valid peptides or has the low-complexity flag.
  • try_other_enzyme: a remaining row has the hydrophobicity flag, the short-protein flag, or a Poor verdict.
  • consider_alternative: any remaining Moderate row.

These labels do not run another enzyme or predict that the suggested action will improve an experiment.

Step 6c: Export a peptide list

export_peptide_list() filters valid peptides from any digest_protein() tibble and writes them in a format compatible with downstream tools.

peps <- digest_protein(bsa_path, enzyme = "trypsin", missed_cleavages = 1L)

# Skyline transition list: one row per valid peptide per charge state
# Columns: Protein, Peptide Sequence, Precursor Charge, Precursor Mz
export_peptide_list(peps, format = "skyline", charges = 2:3)
#> # A tibble: 216 × 4
#>    Protein                  `Peptide Sequence` `Precursor Charge` `Precursor Mz`
#>    <chr>                    <chr>                           <int>          <dbl>
#>  1 sp|P02769|ALBU_BOVIN Al… MKWVTFISLLLLFSSAY…                  2          1132.
#>  2 sp|P02769|ALBU_BOVIN Al… MKWVTFISLLLLFSSAY…                  3           755.
#>  3 sp|P02769|ALBU_BOVIN Al… WVTFISLLLLFSSAYSR                   2          1002.
#>  4 sp|P02769|ALBU_BOVIN Al… WVTFISLLLLFSSAYSR                   3           668.
#>  5 sp|P02769|ALBU_BOVIN Al… WVTFISLLLLFSSAYSR…                  2          1232.
#>  6 sp|P02769|ALBU_BOVIN Al… WVTFISLLLLFSSAYSR…                  3           821.
#>  7 sp|P02769|ALBU_BOVIN Al… DTHKSEIAHR                          2           597.
#>  8 sp|P02769|ALBU_BOVIN Al… DTHKSEIAHR                          3           399.
#>  9 sp|P02769|ALBU_BOVIN Al… SEIAHRFK                            2           494.
#> 10 sp|P02769|ALBU_BOVIN Al… SEIAHRFK                            3           330.
#> # ℹ 206 more rows
# Generic annotated table: all peptide columns plus gravy, pI, and valid flag
export_peptide_list(peps, format = "generic")
#> # A tibble: 157 × 9
#>    protein_id     peptide start   end length missed_cleavages  gravy    pI valid
#>    <chr>          <chr>   <int> <int>  <int>            <int>  <dbl> <dbl> <lgl>
#>  1 sp|P02769|ALB… MK          1     2      2                0 -1      9.25 FALSE
#>  2 sp|P02769|ALB… MKWVTF…     1    19     19                1  0.984 10.3  TRUE 
#>  3 sp|P02769|ALB… WVTFIS…     3    19     17                0  1.22   9.05 TRUE 
#>  4 sp|P02769|ALB… WVTFIS…     3    23     21                1  1.09  11.1  TRUE 
#>  5 sp|P02769|ALB… GVFR       20    23      4                0  0.525 10.3  FALSE
#>  6 sp|P02769|ALB… GVFRR      20    24      5                1 -0.48  12.5  FALSE
#>  7 sp|P02769|ALB… R          24    24      1                0 -4.5   10.3  FALSE
#>  8 sp|P02769|ALB… RDTHK      24    28      5                1 -3.16   9.25 FALSE
#>  9 sp|P02769|ALB… DTHK       25    28      4                0 -2.82   7.00 FALSE
#> 10 sp|P02769|ALB… DTHKSE…    25    34     10                1 -1.7    7.17 TRUE 
#> # ℹ 147 more rows
# FASTA character vector for valid peptides only
# Each header: >protein_id|start-end
head(export_peptide_list(peps, format = "fasta"))
#> [1] ">sp|P02769|ALBU_BOVIN Albumin OS=Bos taurus OX=9913 GN=ALB PE=1 SV=4|peptide_1-19"
#> [2] "MKWVTFISLLLLFSSAYSR"                                                              
#> [3] ">sp|P02769|ALBU_BOVIN Albumin OS=Bos taurus OX=9913 GN=ALB PE=1 SV=4|peptide_3-19"
#> [4] "WVTFISLLLLFSSAYSR"                                                                
#> [5] ">sp|P02769|ALBU_BOVIN Albumin OS=Bos taurus OX=9913 GN=ALB PE=1 SV=4|peptide_3-23"
#> [6] "WVTFISLLLLFSSAYSRGVFR"

Write directly to a file by passing a path to the file argument:

export_peptide_list(peps, format = "skyline", file = "bsa_transitions.csv")
export_peptide_list(peps, format = "fasta", file = "bsa_peptides.fasta")

Step 7: Quick interactive check

pepvet_check() combines evaluate_digest() and digest_report() in one interactive call. It prints a console report and returns the result invisibly.

result <- pepvet_check(bsa_path, enzyme = "trypsin")
#> 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  [########--]

The returned value is the full evaluate_digest() result list, so you can pipe it into any downstream step:

result <- pepvet_check(bsa_path, enzyme = "trypsin", missed_cleavages = 1L)
result$scores
result$peptides

Step 8: Report to the console

digest_report() prints an ASCII-safe summary for an evaluate_digest() result or a ranked table for a compare_digests() result. Long protein identifiers wrap, and comparison tables simplify when the terminal is narrow. The function returns its input invisibly.

digest_report(ev)
#> 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(comp)
#> pepVet enzyme comparison
#> ------------------------
#> Protein            sp|P02769|ALBU_BOVIN Albumin OS=Bos taurus OX=9913 GN=ALB
#>                    PE=1 SV=4
#> Best score         trypsin (0.885, Good)
#> Rank Enzyme                 S_len S_cov S_cnt S_hyd S_chg Score Verdict
#> -----------------------------------------------------------------------
#>    1 trypsin                0.688 0.997 1.000 0.769 0.778 0.885 Good
#>    2 glutamyl endopeptidase 0.681 0.936 1.000 0.802 0.975 0.884 Good
#>    3 lysc                   0.628 0.857 1.000 0.763 0.776 0.823 Good
#>    4 asp-n endopeptidase    0.494 0.529 0.923 0.725 0.925 0.673 Good
#>    5 chymotrypsin-high      0.477 0.590 0.840 0.549 0.863 0.642 Moderate

digest_report() returns invisible(x), so a script can print the report and retain the object:

# Compare enzymes and print a report
comp <- compare_digests(bsa_path,
  enzymes = c("trypsin", "lysc", "glutamyl endopeptidase")
)
digest_report(comp)

# Get the top model rank directly from the sequence
winner <- recommend_enzyme(bsa_path,
  enzymes = c("trypsin", "lysc", "glutamyl endopeptidase")
)

Additional examples and references

The remaining sections connect the core workflow to a challenging protein, the shipped amino acid data, and the package’s narrower role among proteomics tools.

A challenging protein: Histone H3.1

Histone H3.1 is a package example in which strict tryptic digestion produces many short fragments from its lysine- and arginine-rich N-terminal tail. Many of those fragments fall below pepVet’s conservative 7-residue boundary. This is a scoring result under the active settings, not a universal detection threshold.

ev_h3_trypsin <- evaluate_digest(h3_path, enzyme = "trypsin")
ev_h3_trypsin$scores$verdict
#> [1] "Moderate"

In this in-silico comparison, LysC recognises only lysine and cleaves less frequently on H3.1, producing longer peptides with a higher score under the default settings:

compare_digests(
  h3_path,
  enzymes = c(
    "trypsin", "lysc", "glutamyl endopeptidase",
    "asp-n endopeptidase"
  )
)
#> # A tibble: 4 × 13
#>   enzyme protein_id S_length S_coverage S_count S_hydro S_charge composite_score
#>   <chr>  <chr>         <dbl>      <dbl>   <dbl>   <dbl>    <dbl>           <dbl>
#> 1 lysc   sp|P68431…    0.593      0.735   1       0.625    0.938           0.769
#> 2 tryps… sp|P68431…    0.305      0.632   0.662   0.833    0.833           0.619
#> 3 gluta… sp|P68431…    0.467      0.404   1       0.571    0.714           0.602
#> 4 asp-n… sp|P68431…    0.333      0.404   0.640   1        1               0.578
#> # ℹ 5 more variables: verdict <chr>, median_peptide_length <dbl>,
#> #   preset_used <chr>, n_high_efficiency_sites <int>,
#> #   n_low_efficiency_sites <int>

Amino acid reference data

The package ships aa_properties, a 22-row tibble containing the 20 standard amino acids plus selenocysteine and pyrrolysine.

aa_properties
#> # A tibble: 22 × 6
#>    amino_acid molecular_weight residue_monoisotopic_mass hydrophobicity
#>    <chr>                 <dbl>                     <dbl>          <dbl>
#>  1 A                      89.0                      71.0            1.8
#>  2 C                     121.                      103.             2.5
#>  3 D                     133.                      115.            -3.5
#>  4 E                     147.                      129.            -3.5
#>  5 F                     165.                      147.             2.8
#>  6 G                      75.0                      57.0           -0.4
#>  7 H                     155.                      137.            -3.2
#>  8 I                     131.                      113.             4.5
#>  9 K                     146.                      128.            -3.9
#> 10 L                     131.                      113.             3.8
#> # ℹ 12 more rows
#> # ℹ 2 more variables: pKa_side_chain <dbl>, is_basic <lgl>

The kyte_doolittle column contains the Kyte-Doolittle (1982) hydrophobicity scale used in S_hydro. The is_basic flag supports S_charge, and the pKa_side_chain column holds reference pKa values for the seven ionisable residues (C, D, E, H, K, R, Y) used in calculate_pI().

How pepVet differs from common tools

pepVet covers a narrow part of the workflow. It is not a spectral library builder or a peptide detectability predictor. It compares enzyme-workflow combinations using explicit digest-level criteria before acquisition. This describes the package scope rather than an experimental performance claim.

The tool-comparison vignette compares pepVet against five tools on a panel of five proteins and five enzymes. It covers baseline peptide overlap, capability differences across 16 dimensions, the scoring model in practice, workflow preset effects, pipeline integration with PeptideRanger, and a binary versus graded classification comparison with Protein Cleaver.

Session info

sessionInfo()
#> R version 4.6.1 (2026-06-24)
#> Platform: x86_64-pc-linux-gnu
#> Running under: Ubuntu 26.04 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.32.so;  LAPACK version 3.12.0
#> 
#> locale:
#>  [1] LC_CTYPE=en_US.UTF-8       LC_NUMERIC=C              
#>  [3] LC_TIME=en_US.UTF-8        LC_COLLATE=en_US.UTF-8    
#>  [5] LC_MONETARY=en_US.UTF-8    LC_MESSAGES=en_US.UTF-8   
#>  [7] LC_PAPER=en_US.UTF-8       LC_NAME=C                 
#>  [9] LC_ADDRESS=C               LC_TELEPHONE=C            
#> [11] LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=C       
#> 
#> time zone: Etc/UTC
#> tzcode source: system (glibc)
#> 
#> attached base packages:
#> [1] stats     graphics  grDevices utils     datasets  methods   base     
#> 
#> other attached packages:
#> [1] pepVet_0.99.0  rmarkdown_2.31
#> 
#> 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       jsonlite_2.0.0      
#> [10] glue_1.8.1           S4Vectors_0.51.5     buildtools_1.0.0    
#> [13] Biostrings_2.81.3    htmltools_0.5.9      maketools_1.3.2     
#> [16] sys_3.4.3            sass_0.4.10          stats4_4.6.1        
#> [19] cleaver_1.51.0       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       pkgconfig_2.0.3      XVector_0.53.0      
#> [31] digest_0.6.39        R6_2.6.1             utf8_1.2.6          
#> [34] pillar_1.11.1        magrittr_2.0.5       bslib_0.11.0        
#> [37] tools_4.6.1          BiocGenerics_0.59.10 cachem_1.1.0