Skip to content

Commit 905c22f

Browse files
committed
adjust workflow to improved error handling
1 parent 2accae1 commit 905c22f

1 file changed

Lines changed: 50 additions & 18 deletions

File tree

src/WorkflowTest.py

Lines changed: 50 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -62,8 +62,11 @@ def configure(self) -> None:
6262
if self.params.get("generate-decoys", True):
6363
st.info("""
6464
**Decoy Database Settings:**
65-
* **decoy_string**: Prefix/suffix for decoy protein accessions
66-
* **method**: Method for generating decoys (reverse, shuffle)
65+
* **method**: How decoy sequences are generated from target protein sequences.
66+
*Reverse* creates decoys by reversing each sequence, while *shuffle* randomly
67+
rearranges the amino acids. Both methods preserve the amino acid composition
68+
of the original protein, ensuring decoys have similar properties to real sequences
69+
for accurate false discovery rate (FDR) estimation.
6770
""")
6871
self.ui.input_TOPP(
6972
"DecoyDatabase",
@@ -72,7 +75,7 @@ def configure(self) -> None:
7275
"decoy_string_position": "prefix",
7376
"method": "reverse",
7477
},
75-
include_parameters=["decoy_string", "method"],
78+
include_parameters=["method"],
7679
)
7780

7881
comet_info = """
@@ -234,7 +237,7 @@ def configure(self) -> None:
234237
# Store in session_state for results section compatibility
235238
st.session_state["mzML_groups"] = group_map
236239

237-
def execution(self) -> None:
240+
def execution(self) -> bool:
238241
"""
239242
Refactored TOPP workflow execution:
240243
- Per-sample: CometAdapter -> PercolatorAdapter -> IDFilter
@@ -245,37 +248,44 @@ def execution(self) -> None:
245248
# ================================
246249
if not self.params.get("mzML-files"):
247250
st.error("No mzML files selected.")
248-
return
251+
return False
249252

250253
if not self.params.get("fasta-file"):
251254
st.error("No FASTA file selected.")
252-
return
255+
return False
253256

254257
in_mzML = self.file_manager.get_files(self.params["mzML-files"])
255258
fasta_file = self.file_manager.get_files([self.params["fasta-file"]])[0]
256259

257260
if len(in_mzML) < 1:
258261
st.error("At least one mzML file is required.")
259-
return
262+
return False
260263

261264
fasta_path = Path(fasta_file)
262265

266+
self.logger.log(f"📂 Loaded {len(in_mzML)} sample(s)")
267+
263268
if self.params.get("generate-decoys", True):
264269
decoy_fasta = fasta_path.with_suffix(".decoy.fasta")
265270
# Get decoy_string from DecoyDatabase params
266271
decoy_string = self.params.get("DecoyDatabase", {}).get("decoy_string", "rev_")
267272

268273
if not decoy_fasta.exists():
274+
self.logger.log("🧬 Generating decoy database...")
269275
st.info("Generating decoy FASTA database...")
270-
self.executor.run_topp(
276+
if not self.executor.run_topp(
271277
"DecoyDatabase",
272278
{"in": [str(fasta_path)], "out": [str(decoy_fasta)]},
273-
)
279+
):
280+
self.logger.log("Workflow stopped due to error")
281+
return False
282+
self.logger.log("✅ Decoy database ready")
274283
st.success(f"Using decoy FASTA: {decoy_fasta.name}")
275284
database_fasta = decoy_fasta
276285
else:
277286
# Get decoy_string from CometAdapter params
278287
decoy_string = self.params.get("CometAdapter", {}).get("PeptideIndexing:decoy_string", "rev_")
288+
self.logger.log("📄 Using existing FASTA database")
279289
st.info(f"Using original FASTA: {fasta_path.name}")
280290
database_fasta = fasta_path
281291

@@ -293,6 +303,8 @@ def execution(self) -> None:
293303
for d in [comet_dir, perc_dir, filter_dir, quant_dir]:
294304
d.mkdir(parents=True, exist_ok=True)
295305

306+
self.logger.log("📁 Output directories created")
307+
296308
# ================================
297309
# 2️⃣ File path definitions (per sample)
298310
# ================================
@@ -313,50 +325,64 @@ def execution(self) -> None:
313325
stem = Path(mz).stem
314326
st.info(f"Processing sample: {stem}")
315327

328+
self.logger.log("🔬 Starting per-sample processing...")
329+
316330
# --- CometAdapter ---
331+
self.logger.log("🔎 Running peptide search...")
317332
with st.spinner(f"CometAdapter ({stem})"):
318333
comet_extra_params = {"database": str(database_fasta)}
319334
if self.params.get("generate-decoys", True):
320335
# Propagate decoy_string from DecoyDatabase
321336
comet_extra_params["PeptideIndexing:decoy_string"] = decoy_string
322337

323-
self.executor.run_topp(
338+
if not self.executor.run_topp(
324339
"CometAdapter",
325340
{
326341
"in": in_mzML,
327342
"out": comet_results,
328343
},
329344
comet_extra_params,
330-
)
345+
):
346+
self.logger.log("Workflow stopped due to error")
347+
return False
348+
self.logger.log("✅ Peptide search complete")
331349

332350
# if not Path(comet_results).exists():
333351
# st.error(f"CometAdapter failed for {stem}")
334352
# st.stop()
335353

336354
# --- PercolatorAdapter ---
355+
self.logger.log("📊 Running rescoring...")
337356
with st.spinner(f"PercolatorAdapter ({stem})"):
338-
self.executor.run_topp(
357+
if not self.executor.run_topp(
339358
"PercolatorAdapter",
340359
{
341360
"in": comet_results,
342361
"out": percolator_results,
343362
},
344363
{"decoy_pattern": decoy_string}, # Always propagated from upstream
345-
)
346-
364+
):
365+
self.logger.log("Workflow stopped due to error")
366+
return False
367+
self.logger.log("✅ Rescoring complete")
368+
347369
# if not Path(percolator_results[i]).exists():
348370
# st.error(f"PercolatorAdapter failed for {stem}")
349371
# st.stop()
350372

351373
# --- IDFilter ---
374+
self.logger.log("🔧 Filtering identifications...")
352375
with st.spinner(f"IDFilter ({stem})"):
353-
self.executor.run_topp(
376+
if not self.executor.run_topp(
354377
"IDFilter",
355378
{
356379
"in": percolator_results,
357380
"out": filter_results,
358381
},
359-
)
382+
):
383+
self.logger.log("Workflow stopped due to error")
384+
return False
385+
self.logger.log("✅ Filtering complete")
360386

361387
# if not Path(filter_results[i]).exists():
362388
# st.error(f"IDFilter failed for {stem}")
@@ -367,6 +393,7 @@ def execution(self) -> None:
367393
# # ================================
368394
# # 4️⃣ ProteomicsLFQ (cross-sample)
369395
# # ================================
396+
self.logger.log("📈 Running cross-sample quantification...")
370397
st.info("Running ProteomicsLFQ (cross-sample quantification)")
371398

372399
quant_mztab = str(quant_dir / "openms_quant.mzTab")
@@ -389,7 +416,7 @@ def execution(self) -> None:
389416
st.write("**combined_ids:**", combined_ids)
390417
st.write("**combined_ids type:**", type(combined_ids).__name__)
391418

392-
self.executor.run_topp(
419+
if not self.executor.run_topp(
393420
"ProteomicsLFQ",
394421
{
395422
"in": [in_mzML],
@@ -407,7 +434,10 @@ def execution(self) -> None:
407434
"PeptideQuantification:extract:IM_window": "0.0",
408435
"PeptideQuantification:faims:merge_features": "false",
409436
}
410-
)
437+
):
438+
self.logger.log("Workflow stopped due to error")
439+
return False
440+
self.logger.log("✅ Quantification complete")
411441

412442
# if not Path(quant_mztab).exists():
413443
# st.error("ProteomicsLFQ failed: mzTab not created")
@@ -427,6 +457,8 @@ def execution(self) -> None:
427457
st.write(f"- consensusXML: {quant_cxml}")
428458
st.write(f"- MSstats CSV: {quant_msstats}")
429459

460+
return True
461+
430462
@st.fragment
431463
def results(self) -> None:
432464

0 commit comments

Comments
 (0)