Skip to content

Commit dcaf7b7

Browse files
committed
selective decoy database generation
1 parent 578b7da commit dcaf7b7

1 file changed

Lines changed: 76 additions & 25 deletions

File tree

src/WorkflowTest.py

Lines changed: 76 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -42,15 +42,56 @@ def configure(self) -> None:
4242
t = st.tabs(["**Identification**", "**Rescoring**", "**Filtering**", "**Quantification**", "**Group Selection**"])
4343

4444
with t[0]:
45-
st.info("""
45+
# Checkbox for decoy generation
46+
# reactive=True ensures the parent configure() fragment re-runs when checkbox changes,
47+
# so conditional UI (DecoyDatabase settings) updates immediately
48+
self.ui.input_widget(
49+
key="generate-decoys",
50+
default=True,
51+
name="Generate Decoy Database",
52+
widget_type="checkbox",
53+
help="Generate reversed decoy sequences for FDR calculation. Disable if your FASTA already contains decoys.",
54+
reactive=True,
55+
)
56+
57+
# Reload params to get current checkbox value after it was saved
58+
self.params = self.parameter_manager.get_parameters_from_json()
59+
60+
# Show DecoyDatabase settings if generating decoys
61+
if self.params.get("generate-decoys", True):
62+
st.info("""
63+
**Decoy Database Settings:**
64+
* **decoy_string**: Prefix/suffix for decoy protein accessions
65+
* **method**: Method for generating decoys (reverse, shuffle)
66+
""")
67+
self.ui.input_TOPP(
68+
"DecoyDatabase",
69+
custom_defaults={
70+
"decoy_string": "rev_",
71+
"decoy_string_position": "prefix",
72+
"method": "reverse",
73+
},
74+
include_parameters=["decoy_string", "decoy_string_position", "method"],
75+
)
76+
77+
comet_info = """
4678
**Identification (Comet):**
4779
* **enzyme**: The enzyme used for peptide digestion.
4880
* **missed_cleavages**: Number of possible cleavage sites missed by the enzyme. It has no effect if enzyme is unspecific cleavage.
4981
* **fixed_modifications**: Fixed modifications, specified using Unimod (www.unimod.org) terms, e.g. 'Carbamidomethyl (C)' or 'Oxidation (M)'
5082
* **variable_modifications**: Variable modifications, specified using Unimod (www.unimod.org) terms, e.g. 'Carbamidomethyl (C)' or 'Oxidation (M)'
51-
* **PeptideIndexing:decoy_string**: String that was appended (or prefixed - see 'decoy_string_position' flag below) to the accessions
83+
"""
84+
if not self.params.get("generate-decoys", True):
85+
comet_info += """* **PeptideIndexing:decoy_string**: String that was appended (or prefixed - see 'decoy_string_position' flag below) to the accessions
5286
in the protein database to indicate decoy proteins.
53-
""")
87+
"""
88+
st.info(comet_info)
89+
90+
comet_include = ["enzyme", "missed_cleavages", "fixed_modifications", "variable_modifications"]
91+
if not self.params.get("generate-decoys", True):
92+
# Only show decoy_string when not generating decoys
93+
comet_include.append("PeptideIndexing:decoy_string")
94+
5495
self.ui.input_TOPP(
5596
"CometAdapter",
5697
custom_defaults={
@@ -72,17 +113,19 @@ def configure(self) -> None:
72113
"PeptideIndexing:unmatched_action": "warn",
73114
"PeptideIndexing:decoy_string": "rev_"
74115
},
75-
include_parameters=["enzyme", "missed_cleavages","fixed_modifications", "variable_modifications", "PeptideIndexing:decoy_string"],
116+
include_parameters=comet_include,
76117
)
77118

78119
with t[1]:
79120
st.info("""
80121
**Rescoring (Percolator):**
81-
* **decoy_pattern**: Define the text pattern to identify the decoy proteins and/or PSMs, set this up if the label that identifies the decoys in the database is not the default (Only valid if option -protein_level_fdrs is active).
82122
* **post_processing_tdc**: Use target-decoy competition to assign q-values and PEPs.
83123
* **score_type**: Type of the peptide main score
84124
* **subset_max_train**: Only train an SVM on a subset of <x> PSMs, and use the resulting score vector to evaluate the other PSMs. Recommended when analyzing huge numbers (>1 million) of PSMs. When set to 0, all PSMs are used for training as normal.
85125
""")
126+
# decoy_pattern is always derived from upstream, never shown
127+
percolator_include = ["post_processing_tdc", "score_type", "subset_max_train"]
128+
86129
self.ui.input_TOPP(
87130
"PercolatorAdapter",
88131
custom_defaults={
@@ -92,7 +135,7 @@ def configure(self) -> None:
92135
"score_type": "pep",
93136
"post_processing_tdc": "true",
94137
},
95-
include_parameters=["decoy_pattern", "post_processing_tdc", "score_type", "subset_max_train"],
138+
include_parameters=percolator_include,
96139
)
97140

98141
with t[2]:
@@ -224,19 +267,25 @@ def execution(self) -> None:
224267
return
225268

226269
fasta_path = Path(fasta_file)
227-
# decoy_fasta = fasta_path.with_suffix(".decoy.fasta")
228-
229-
# if not decoy_fasta.exists():
230-
# st.info("Generating decoy FASTA database...")
231-
# self.executor.run_topp(
232-
# "DecoyDatabase",
233-
# {
234-
# "in": [str(fasta_path)],
235-
# "out": [str(decoy_fasta)],
236-
# },
237-
# )
238-
239-
# st.success(f"Using decoy FASTA: {decoy_fasta.name}")
270+
271+
if self.params.get("generate-decoys", True):
272+
decoy_fasta = fasta_path.with_suffix(".decoy.fasta")
273+
# Get decoy_string from DecoyDatabase params
274+
decoy_string = self.params.get("DecoyDatabase", {}).get("decoy_string", "rev_")
275+
276+
if not decoy_fasta.exists():
277+
st.info("Generating decoy FASTA database...")
278+
self.executor.run_topp(
279+
"DecoyDatabase",
280+
{"in": [str(fasta_path)], "out": [str(decoy_fasta)]},
281+
)
282+
st.success(f"Using decoy FASTA: {decoy_fasta.name}")
283+
database_fasta = decoy_fasta
284+
else:
285+
# Get decoy_string from CometAdapter params
286+
decoy_string = self.params.get("CometAdapter", {}).get("PeptideIndexing:decoy_string", "rev_")
287+
st.info(f"Using original FASTA: {fasta_path.name}")
288+
database_fasta = fasta_path
240289

241290
# ================================
242291
# 1️⃣ Directory setup
@@ -274,16 +323,18 @@ def execution(self) -> None:
274323

275324
# --- CometAdapter ---
276325
with st.spinner(f"CometAdapter ({stem})"):
326+
comet_extra_params = {"database": str(database_fasta)}
327+
if self.params.get("generate-decoys", True):
328+
# Propagate decoy_string from DecoyDatabase
329+
comet_extra_params["PeptideIndexing:decoy_string"] = decoy_string
330+
277331
self.executor.run_topp(
278332
"CometAdapter",
279333
{
280334
"in": in_mzML,
281335
"out": comet_results,
282336
},
283-
{
284-
# "database": str(decoy_fasta),
285-
"database": str(fasta_path),
286-
},
337+
comet_extra_params,
287338
)
288339

289340
# if not Path(comet_results).exists():
@@ -298,6 +349,7 @@ def execution(self) -> None:
298349
"in": comet_results,
299350
"out": percolator_results,
300351
},
352+
{"decoy_pattern": decoy_string}, # Always propagated from upstream
301353
)
302354

303355
# if not Path(percolator_results[i]).exists():
@@ -355,8 +407,7 @@ def execution(self) -> None:
355407
"out_msstats": [quant_msstats],
356408
},
357409
{
358-
# "fasta": str(decoy_fasta),
359-
"fasta": str(fasta_path),
410+
"fasta": str(database_fasta),
360411
"psmFDR": 0.5,
361412
"proteinFDR": 0.5,
362413
"threads": 12,

0 commit comments

Comments
 (0)