Spaces:
Sleeping
Sleeping
Halper-Stromberg commited on
Commit ·
f72768b
1
Parent(s): 9cb3cbb
Support optional gzip compression for FASTQ output files to reduce size
Browse files- pipeline.py +15 -1
- src/pipeline.py +15 -1
- src/streamlit_app.py +22 -10
- streamlit_app.py +22 -10
pipeline.py
CHANGED
|
@@ -306,7 +306,8 @@ def generate_synthetic_bam(
|
|
| 306 |
work_dir, snvs_bed, fasta_path, depth, vaf, rg_id, rg_sm,
|
| 307 |
insert_size, insert_std, indel_interval, read_length=150,
|
| 308 |
sequencing_mode="hybrid_capture",
|
| 309 |
-
log_func=None, progress_func=None
|
|
|
|
| 310 |
):
|
| 311 |
import pysam
|
| 312 |
from collections import defaultdict
|
|
@@ -521,6 +522,19 @@ def generate_synthetic_bam(
|
|
| 521 |
fastq_r2 = work_dir / "synthetic_R2.fastq"
|
| 522 |
run_cmd(f"samtools fastq -1 {fastq_r1} -2 {fastq_r2} -0 {dev_null} -s {dev_null} {output_bam}", log_func)
|
| 523 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 524 |
if progress_func:
|
| 525 |
progress_func(1.0, "Sorting and indexing BAM...")
|
| 526 |
|
|
|
|
| 306 |
work_dir, snvs_bed, fasta_path, depth, vaf, rg_id, rg_sm,
|
| 307 |
insert_size, insert_std, indel_interval, read_length=150,
|
| 308 |
sequencing_mode="hybrid_capture",
|
| 309 |
+
log_func=None, progress_func=None,
|
| 310 |
+
compress_fastq=False
|
| 311 |
):
|
| 312 |
import pysam
|
| 313 |
from collections import defaultdict
|
|
|
|
| 522 |
fastq_r2 = work_dir / "synthetic_R2.fastq"
|
| 523 |
run_cmd(f"samtools fastq -1 {fastq_r1} -2 {fastq_r2} -0 {dev_null} -s {dev_null} {output_bam}", log_func)
|
| 524 |
|
| 525 |
+
if compress_fastq:
|
| 526 |
+
if progress_func:
|
| 527 |
+
progress_func(0.97, "Compressing FASTQ files (gzip)...")
|
| 528 |
+
import gzip
|
| 529 |
+
import shutil
|
| 530 |
+
log("Compressing FASTQ files to gzip format...", log_func)
|
| 531 |
+
for f_path in [fastq_r1, fastq_r2]:
|
| 532 |
+
gz_path = f_path.with_suffix(".fastq.gz")
|
| 533 |
+
with open(f_path, "rb") as f_in:
|
| 534 |
+
with gzip.open(gz_path, "wb", compresslevel=3) as f_out:
|
| 535 |
+
shutil.copyfileobj(f_in, f_out)
|
| 536 |
+
f_path.unlink()
|
| 537 |
+
|
| 538 |
if progress_func:
|
| 539 |
progress_func(1.0, "Sorting and indexing BAM...")
|
| 540 |
|
src/pipeline.py
CHANGED
|
@@ -306,7 +306,8 @@ def generate_synthetic_bam(
|
|
| 306 |
work_dir, snvs_bed, fasta_path, depth, vaf, rg_id, rg_sm,
|
| 307 |
insert_size, insert_std, indel_interval, read_length=150,
|
| 308 |
sequencing_mode="hybrid_capture",
|
| 309 |
-
log_func=None, progress_func=None
|
|
|
|
| 310 |
):
|
| 311 |
import pysam
|
| 312 |
from collections import defaultdict
|
|
@@ -521,6 +522,19 @@ def generate_synthetic_bam(
|
|
| 521 |
fastq_r2 = work_dir / "synthetic_R2.fastq"
|
| 522 |
run_cmd(f"samtools fastq -1 {fastq_r1} -2 {fastq_r2} -0 {dev_null} -s {dev_null} {output_bam}", log_func)
|
| 523 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 524 |
if progress_func:
|
| 525 |
progress_func(1.0, "Sorting and indexing BAM...")
|
| 526 |
|
|
|
|
| 306 |
work_dir, snvs_bed, fasta_path, depth, vaf, rg_id, rg_sm,
|
| 307 |
insert_size, insert_std, indel_interval, read_length=150,
|
| 308 |
sequencing_mode="hybrid_capture",
|
| 309 |
+
log_func=None, progress_func=None,
|
| 310 |
+
compress_fastq=False
|
| 311 |
):
|
| 312 |
import pysam
|
| 313 |
from collections import defaultdict
|
|
|
|
| 522 |
fastq_r2 = work_dir / "synthetic_R2.fastq"
|
| 523 |
run_cmd(f"samtools fastq -1 {fastq_r1} -2 {fastq_r2} -0 {dev_null} -s {dev_null} {output_bam}", log_func)
|
| 524 |
|
| 525 |
+
if compress_fastq:
|
| 526 |
+
if progress_func:
|
| 527 |
+
progress_func(0.97, "Compressing FASTQ files (gzip)...")
|
| 528 |
+
import gzip
|
| 529 |
+
import shutil
|
| 530 |
+
log("Compressing FASTQ files to gzip format...", log_func)
|
| 531 |
+
for f_path in [fastq_r1, fastq_r2]:
|
| 532 |
+
gz_path = f_path.with_suffix(".fastq.gz")
|
| 533 |
+
with open(f_path, "rb") as f_in:
|
| 534 |
+
with gzip.open(gz_path, "wb", compresslevel=3) as f_out:
|
| 535 |
+
shutil.copyfileobj(f_in, f_out)
|
| 536 |
+
f_path.unlink()
|
| 537 |
+
|
| 538 |
if progress_func:
|
| 539 |
progress_func(1.0, "Sorting and indexing BAM...")
|
| 540 |
|
src/streamlit_app.py
CHANGED
|
@@ -346,6 +346,13 @@ with st.sidebar:
|
|
| 346 |
rg_id = st.text_input("Read Group ID", value="CPDV2510843-SEQ-251103")
|
| 347 |
rg_sm = st.text_input("Sample Name", value="CPDV2510843-SEQ-251103")
|
| 348 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 349 |
st.divider()
|
| 350 |
st.subheader("🛠️ Debug Info")
|
| 351 |
st.caption("Helpful diagnostics for troubleshooting deployment status.")
|
|
@@ -647,6 +654,7 @@ if run_btn:
|
|
| 647 |
sequencing_mode="pcr_amplicon" if seq_mode.startswith("PCR Amplicon") else "hybrid_capture",
|
| 648 |
log_func=append_log,
|
| 649 |
progress_func=bam_progress,
|
|
|
|
| 650 |
)
|
| 651 |
|
| 652 |
update_progress(1.0, "Done!")
|
|
@@ -662,8 +670,8 @@ if run_btn:
|
|
| 662 |
static_dest_cwd = Path("static") / work_dir_name
|
| 663 |
static_dest_script = Path(__file__).parent / "static" / work_dir_name
|
| 664 |
|
| 665 |
-
fastq_r1_path = work_dir / "synthetic_R1.fastq"
|
| 666 |
-
fastq_r2_path = work_dir / "synthetic_R2.fastq"
|
| 667 |
|
| 668 |
for dest in [static_dest_cwd, static_dest_script]:
|
| 669 |
dest.mkdir(parents=True, exist_ok=True)
|
|
@@ -677,9 +685,9 @@ if run_btn:
|
|
| 677 |
if mane_transcripts_bed and mane_transcripts_bed.exists():
|
| 678 |
shutil.copy(mane_transcripts_bed, dest / "mane_transcripts.bed")
|
| 679 |
if fastq_r1_path.exists():
|
| 680 |
-
shutil.copy(fastq_r1_path, dest /
|
| 681 |
if fastq_r2_path.exists():
|
| 682 |
-
shutil.copy(fastq_r2_path, dest /
|
| 683 |
|
| 684 |
# Store URLs and path strings — never load large files into session_state memory
|
| 685 |
st.session_state["results"] = {
|
|
@@ -699,10 +707,11 @@ if run_btn:
|
|
| 699 |
"igv_bed_url": f"/app/static/{work_dir_name}/igv_variant_navigator.bed",
|
| 700 |
"fully_covered_bed_url": f"/app/static/{work_dir_name}/fully_covered_exons.bed" if fully_bed_path and fully_bed_path.exists() else None,
|
| 701 |
"mane_transcripts_bed_url": f"/app/static/{work_dir_name}/mane_transcripts.bed" if mane_transcripts_bed and mane_transcripts_bed.exists() else None,
|
| 702 |
-
"fastq_r1_url": f"/app/static/{work_dir_name}/
|
| 703 |
-
"fastq_r2_url": f"/app/static/{work_dir_name}/
|
| 704 |
"work_dir_name": work_dir_name,
|
| 705 |
"genome_version": genome_version,
|
|
|
|
| 706 |
}
|
| 707 |
st.session_state["log_lines"] = log_lines[:]
|
| 708 |
|
|
@@ -861,8 +870,11 @@ if "results" in st.session_state:
|
|
| 861 |
|
| 862 |
# Row 3 of download buttons (FASTQ R1/R2)
|
| 863 |
dl7, dl8, dl9 = st.columns(3)
|
|
|
|
|
|
|
|
|
|
| 864 |
with dl7:
|
| 865 |
-
st.markdown("**Synthetic FASTQ R1 (Forward)**")
|
| 866 |
fastq_r1_path = Path(res["fastq_r1_path"]) if res.get("fastq_r1_path") else None
|
| 867 |
if fastq_r1_path and fastq_r1_path.exists():
|
| 868 |
if st.checkbox("Prepare FASTQ R1", key="prep_r1", help="Click to load R1 FASTQ file into memory to prepare it for download."):
|
|
@@ -870,12 +882,12 @@ if "results" in st.session_state:
|
|
| 870 |
st.download_button(
|
| 871 |
"⬇ Download FASTQ R1",
|
| 872 |
data=f,
|
| 873 |
-
file_name="synthetic_R1
|
| 874 |
mime="application/octet-stream",
|
| 875 |
use_container_width=True,
|
| 876 |
)
|
| 877 |
with dl8:
|
| 878 |
-
st.markdown("**Synthetic FASTQ R2 (Reverse)**")
|
| 879 |
fastq_r2_path = Path(res["fastq_r2_path"]) if res.get("fastq_r2_path") else None
|
| 880 |
if fastq_r2_path and fastq_r2_path.exists():
|
| 881 |
if st.checkbox("Prepare FASTQ R2", key="prep_r2", help="Click to load R2 FASTQ file into memory to prepare it for download."):
|
|
@@ -883,7 +895,7 @@ if "results" in st.session_state:
|
|
| 883 |
st.download_button(
|
| 884 |
"⬇ Download FASTQ R2",
|
| 885 |
data=f,
|
| 886 |
-
file_name="synthetic_R2
|
| 887 |
mime="application/octet-stream",
|
| 888 |
use_container_width=True,
|
| 889 |
)
|
|
|
|
| 346 |
rg_id = st.text_input("Read Group ID", value="CPDV2510843-SEQ-251103")
|
| 347 |
rg_sm = st.text_input("Sample Name", value="CPDV2510843-SEQ-251103")
|
| 348 |
|
| 349 |
+
st.subheader("FASTQ Output")
|
| 350 |
+
compress_fastq = st.checkbox(
|
| 351 |
+
"Gzip FASTQ output (.fastq.gz)",
|
| 352 |
+
value=True,
|
| 353 |
+
help="Compress the generated FASTQ files using gzip. This makes the files about 4-5x smaller, saving disk space and download time."
|
| 354 |
+
)
|
| 355 |
+
|
| 356 |
st.divider()
|
| 357 |
st.subheader("🛠️ Debug Info")
|
| 358 |
st.caption("Helpful diagnostics for troubleshooting deployment status.")
|
|
|
|
| 654 |
sequencing_mode="pcr_amplicon" if seq_mode.startswith("PCR Amplicon") else "hybrid_capture",
|
| 655 |
log_func=append_log,
|
| 656 |
progress_func=bam_progress,
|
| 657 |
+
compress_fastq=compress_fastq,
|
| 658 |
)
|
| 659 |
|
| 660 |
update_progress(1.0, "Done!")
|
|
|
|
| 670 |
static_dest_cwd = Path("static") / work_dir_name
|
| 671 |
static_dest_script = Path(__file__).parent / "static" / work_dir_name
|
| 672 |
|
| 673 |
+
fastq_r1_path = work_dir / ("synthetic_R1.fastq.gz" if compress_fastq else "synthetic_R1.fastq")
|
| 674 |
+
fastq_r2_path = work_dir / ("synthetic_R2.fastq.gz" if compress_fastq else "synthetic_R2.fastq")
|
| 675 |
|
| 676 |
for dest in [static_dest_cwd, static_dest_script]:
|
| 677 |
dest.mkdir(parents=True, exist_ok=True)
|
|
|
|
| 685 |
if mane_transcripts_bed and mane_transcripts_bed.exists():
|
| 686 |
shutil.copy(mane_transcripts_bed, dest / "mane_transcripts.bed")
|
| 687 |
if fastq_r1_path.exists():
|
| 688 |
+
shutil.copy(fastq_r1_path, dest / fastq_r1_path.name)
|
| 689 |
if fastq_r2_path.exists():
|
| 690 |
+
shutil.copy(fastq_r2_path, dest / fastq_r2_path.name)
|
| 691 |
|
| 692 |
# Store URLs and path strings — never load large files into session_state memory
|
| 693 |
st.session_state["results"] = {
|
|
|
|
| 707 |
"igv_bed_url": f"/app/static/{work_dir_name}/igv_variant_navigator.bed",
|
| 708 |
"fully_covered_bed_url": f"/app/static/{work_dir_name}/fully_covered_exons.bed" if fully_bed_path and fully_bed_path.exists() else None,
|
| 709 |
"mane_transcripts_bed_url": f"/app/static/{work_dir_name}/mane_transcripts.bed" if mane_transcripts_bed and mane_transcripts_bed.exists() else None,
|
| 710 |
+
"fastq_r1_url": f"/app/static/{work_dir_name}/{fastq_r1_path.name}" if fastq_r1_path.exists() else None,
|
| 711 |
+
"fastq_r2_url": f"/app/static/{work_dir_name}/{fastq_r2_path.name}" if fastq_r2_path.exists() else None,
|
| 712 |
"work_dir_name": work_dir_name,
|
| 713 |
"genome_version": genome_version,
|
| 714 |
+
"compress_fastq": compress_fastq,
|
| 715 |
}
|
| 716 |
st.session_state["log_lines"] = log_lines[:]
|
| 717 |
|
|
|
|
| 870 |
|
| 871 |
# Row 3 of download buttons (FASTQ R1/R2)
|
| 872 |
dl7, dl8, dl9 = st.columns(3)
|
| 873 |
+
is_compressed = res.get("compress_fastq", False)
|
| 874 |
+
ext = ".fastq.gz" if is_compressed else ".fastq"
|
| 875 |
+
|
| 876 |
with dl7:
|
| 877 |
+
st.markdown(f"**Synthetic FASTQ R1 (Forward){' (gzipped)' if is_compressed else ''}**")
|
| 878 |
fastq_r1_path = Path(res["fastq_r1_path"]) if res.get("fastq_r1_path") else None
|
| 879 |
if fastq_r1_path and fastq_r1_path.exists():
|
| 880 |
if st.checkbox("Prepare FASTQ R1", key="prep_r1", help="Click to load R1 FASTQ file into memory to prepare it for download."):
|
|
|
|
| 882 |
st.download_button(
|
| 883 |
"⬇ Download FASTQ R1",
|
| 884 |
data=f,
|
| 885 |
+
file_name=f"synthetic_R1{ext}",
|
| 886 |
mime="application/octet-stream",
|
| 887 |
use_container_width=True,
|
| 888 |
)
|
| 889 |
with dl8:
|
| 890 |
+
st.markdown(f"**Synthetic FASTQ R2 (Reverse){' (gzipped)' if is_compressed else ''}**")
|
| 891 |
fastq_r2_path = Path(res["fastq_r2_path"]) if res.get("fastq_r2_path") else None
|
| 892 |
if fastq_r2_path and fastq_r2_path.exists():
|
| 893 |
if st.checkbox("Prepare FASTQ R2", key="prep_r2", help="Click to load R2 FASTQ file into memory to prepare it for download."):
|
|
|
|
| 895 |
st.download_button(
|
| 896 |
"⬇ Download FASTQ R2",
|
| 897 |
data=f,
|
| 898 |
+
file_name=f"synthetic_R2{ext}",
|
| 899 |
mime="application/octet-stream",
|
| 900 |
use_container_width=True,
|
| 901 |
)
|
streamlit_app.py
CHANGED
|
@@ -346,6 +346,13 @@ with st.sidebar:
|
|
| 346 |
rg_id = st.text_input("Read Group ID", value="CPDV2510843-SEQ-251103")
|
| 347 |
rg_sm = st.text_input("Sample Name", value="CPDV2510843-SEQ-251103")
|
| 348 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 349 |
st.divider()
|
| 350 |
st.subheader("🛠️ Debug Info")
|
| 351 |
st.caption("Helpful diagnostics for troubleshooting deployment status.")
|
|
@@ -647,6 +654,7 @@ if run_btn:
|
|
| 647 |
sequencing_mode="pcr_amplicon" if seq_mode.startswith("PCR Amplicon") else "hybrid_capture",
|
| 648 |
log_func=append_log,
|
| 649 |
progress_func=bam_progress,
|
|
|
|
| 650 |
)
|
| 651 |
|
| 652 |
update_progress(1.0, "Done!")
|
|
@@ -662,8 +670,8 @@ if run_btn:
|
|
| 662 |
static_dest_cwd = Path("static") / work_dir_name
|
| 663 |
static_dest_script = Path(__file__).parent / "static" / work_dir_name
|
| 664 |
|
| 665 |
-
fastq_r1_path = work_dir / "synthetic_R1.fastq"
|
| 666 |
-
fastq_r2_path = work_dir / "synthetic_R2.fastq"
|
| 667 |
|
| 668 |
for dest in [static_dest_cwd, static_dest_script]:
|
| 669 |
dest.mkdir(parents=True, exist_ok=True)
|
|
@@ -677,9 +685,9 @@ if run_btn:
|
|
| 677 |
if mane_transcripts_bed and mane_transcripts_bed.exists():
|
| 678 |
shutil.copy(mane_transcripts_bed, dest / "mane_transcripts.bed")
|
| 679 |
if fastq_r1_path.exists():
|
| 680 |
-
shutil.copy(fastq_r1_path, dest /
|
| 681 |
if fastq_r2_path.exists():
|
| 682 |
-
shutil.copy(fastq_r2_path, dest /
|
| 683 |
|
| 684 |
# Store URLs and path strings — never load large files into session_state memory
|
| 685 |
st.session_state["results"] = {
|
|
@@ -699,10 +707,11 @@ if run_btn:
|
|
| 699 |
"igv_bed_url": f"/app/static/{work_dir_name}/igv_variant_navigator.bed",
|
| 700 |
"fully_covered_bed_url": f"/app/static/{work_dir_name}/fully_covered_exons.bed" if fully_bed_path and fully_bed_path.exists() else None,
|
| 701 |
"mane_transcripts_bed_url": f"/app/static/{work_dir_name}/mane_transcripts.bed" if mane_transcripts_bed and mane_transcripts_bed.exists() else None,
|
| 702 |
-
"fastq_r1_url": f"/app/static/{work_dir_name}/
|
| 703 |
-
"fastq_r2_url": f"/app/static/{work_dir_name}/
|
| 704 |
"work_dir_name": work_dir_name,
|
| 705 |
"genome_version": genome_version,
|
|
|
|
| 706 |
}
|
| 707 |
st.session_state["log_lines"] = log_lines[:]
|
| 708 |
|
|
@@ -861,8 +870,11 @@ if "results" in st.session_state:
|
|
| 861 |
|
| 862 |
# Row 3 of download buttons (FASTQ R1/R2)
|
| 863 |
dl7, dl8, dl9 = st.columns(3)
|
|
|
|
|
|
|
|
|
|
| 864 |
with dl7:
|
| 865 |
-
st.markdown("**Synthetic FASTQ R1 (Forward)**")
|
| 866 |
fastq_r1_path = Path(res["fastq_r1_path"]) if res.get("fastq_r1_path") else None
|
| 867 |
if fastq_r1_path and fastq_r1_path.exists():
|
| 868 |
if st.checkbox("Prepare FASTQ R1", key="prep_r1", help="Click to load R1 FASTQ file into memory to prepare it for download."):
|
|
@@ -870,12 +882,12 @@ if "results" in st.session_state:
|
|
| 870 |
st.download_button(
|
| 871 |
"⬇ Download FASTQ R1",
|
| 872 |
data=f,
|
| 873 |
-
file_name="synthetic_R1
|
| 874 |
mime="application/octet-stream",
|
| 875 |
use_container_width=True,
|
| 876 |
)
|
| 877 |
with dl8:
|
| 878 |
-
st.markdown("**Synthetic FASTQ R2 (Reverse)**")
|
| 879 |
fastq_r2_path = Path(res["fastq_r2_path"]) if res.get("fastq_r2_path") else None
|
| 880 |
if fastq_r2_path and fastq_r2_path.exists():
|
| 881 |
if st.checkbox("Prepare FASTQ R2", key="prep_r2", help="Click to load R2 FASTQ file into memory to prepare it for download."):
|
|
@@ -883,7 +895,7 @@ if "results" in st.session_state:
|
|
| 883 |
st.download_button(
|
| 884 |
"⬇ Download FASTQ R2",
|
| 885 |
data=f,
|
| 886 |
-
file_name="synthetic_R2
|
| 887 |
mime="application/octet-stream",
|
| 888 |
use_container_width=True,
|
| 889 |
)
|
|
|
|
| 346 |
rg_id = st.text_input("Read Group ID", value="CPDV2510843-SEQ-251103")
|
| 347 |
rg_sm = st.text_input("Sample Name", value="CPDV2510843-SEQ-251103")
|
| 348 |
|
| 349 |
+
st.subheader("FASTQ Output")
|
| 350 |
+
compress_fastq = st.checkbox(
|
| 351 |
+
"Gzip FASTQ output (.fastq.gz)",
|
| 352 |
+
value=True,
|
| 353 |
+
help="Compress the generated FASTQ files using gzip. This makes the files about 4-5x smaller, saving disk space and download time."
|
| 354 |
+
)
|
| 355 |
+
|
| 356 |
st.divider()
|
| 357 |
st.subheader("🛠️ Debug Info")
|
| 358 |
st.caption("Helpful diagnostics for troubleshooting deployment status.")
|
|
|
|
| 654 |
sequencing_mode="pcr_amplicon" if seq_mode.startswith("PCR Amplicon") else "hybrid_capture",
|
| 655 |
log_func=append_log,
|
| 656 |
progress_func=bam_progress,
|
| 657 |
+
compress_fastq=compress_fastq,
|
| 658 |
)
|
| 659 |
|
| 660 |
update_progress(1.0, "Done!")
|
|
|
|
| 670 |
static_dest_cwd = Path("static") / work_dir_name
|
| 671 |
static_dest_script = Path(__file__).parent / "static" / work_dir_name
|
| 672 |
|
| 673 |
+
fastq_r1_path = work_dir / ("synthetic_R1.fastq.gz" if compress_fastq else "synthetic_R1.fastq")
|
| 674 |
+
fastq_r2_path = work_dir / ("synthetic_R2.fastq.gz" if compress_fastq else "synthetic_R2.fastq")
|
| 675 |
|
| 676 |
for dest in [static_dest_cwd, static_dest_script]:
|
| 677 |
dest.mkdir(parents=True, exist_ok=True)
|
|
|
|
| 685 |
if mane_transcripts_bed and mane_transcripts_bed.exists():
|
| 686 |
shutil.copy(mane_transcripts_bed, dest / "mane_transcripts.bed")
|
| 687 |
if fastq_r1_path.exists():
|
| 688 |
+
shutil.copy(fastq_r1_path, dest / fastq_r1_path.name)
|
| 689 |
if fastq_r2_path.exists():
|
| 690 |
+
shutil.copy(fastq_r2_path, dest / fastq_r2_path.name)
|
| 691 |
|
| 692 |
# Store URLs and path strings — never load large files into session_state memory
|
| 693 |
st.session_state["results"] = {
|
|
|
|
| 707 |
"igv_bed_url": f"/app/static/{work_dir_name}/igv_variant_navigator.bed",
|
| 708 |
"fully_covered_bed_url": f"/app/static/{work_dir_name}/fully_covered_exons.bed" if fully_bed_path and fully_bed_path.exists() else None,
|
| 709 |
"mane_transcripts_bed_url": f"/app/static/{work_dir_name}/mane_transcripts.bed" if mane_transcripts_bed and mane_transcripts_bed.exists() else None,
|
| 710 |
+
"fastq_r1_url": f"/app/static/{work_dir_name}/{fastq_r1_path.name}" if fastq_r1_path.exists() else None,
|
| 711 |
+
"fastq_r2_url": f"/app/static/{work_dir_name}/{fastq_r2_path.name}" if fastq_r2_path.exists() else None,
|
| 712 |
"work_dir_name": work_dir_name,
|
| 713 |
"genome_version": genome_version,
|
| 714 |
+
"compress_fastq": compress_fastq,
|
| 715 |
}
|
| 716 |
st.session_state["log_lines"] = log_lines[:]
|
| 717 |
|
|
|
|
| 870 |
|
| 871 |
# Row 3 of download buttons (FASTQ R1/R2)
|
| 872 |
dl7, dl8, dl9 = st.columns(3)
|
| 873 |
+
is_compressed = res.get("compress_fastq", False)
|
| 874 |
+
ext = ".fastq.gz" if is_compressed else ".fastq"
|
| 875 |
+
|
| 876 |
with dl7:
|
| 877 |
+
st.markdown(f"**Synthetic FASTQ R1 (Forward){' (gzipped)' if is_compressed else ''}**")
|
| 878 |
fastq_r1_path = Path(res["fastq_r1_path"]) if res.get("fastq_r1_path") else None
|
| 879 |
if fastq_r1_path and fastq_r1_path.exists():
|
| 880 |
if st.checkbox("Prepare FASTQ R1", key="prep_r1", help="Click to load R1 FASTQ file into memory to prepare it for download."):
|
|
|
|
| 882 |
st.download_button(
|
| 883 |
"⬇ Download FASTQ R1",
|
| 884 |
data=f,
|
| 885 |
+
file_name=f"synthetic_R1{ext}",
|
| 886 |
mime="application/octet-stream",
|
| 887 |
use_container_width=True,
|
| 888 |
)
|
| 889 |
with dl8:
|
| 890 |
+
st.markdown(f"**Synthetic FASTQ R2 (Reverse){' (gzipped)' if is_compressed else ''}**")
|
| 891 |
fastq_r2_path = Path(res["fastq_r2_path"]) if res.get("fastq_r2_path") else None
|
| 892 |
if fastq_r2_path and fastq_r2_path.exists():
|
| 893 |
if st.checkbox("Prepare FASTQ R2", key="prep_r2", help="Click to load R2 FASTQ file into memory to prepare it for download."):
|
|
|
|
| 895 |
st.download_button(
|
| 896 |
"⬇ Download FASTQ R2",
|
| 897 |
data=f,
|
| 898 |
+
file_name=f"synthetic_R2{ext}",
|
| 899 |
mime="application/octet-stream",
|
| 900 |
use_container_width=True,
|
| 901 |
)
|