From 9c01113286810347b48abba2e79074cfb8ba0574 Mon Sep 17 00:00:00 2001 From: Stavros Giannoukakos Date: Mon, 8 Jun 2026 17:55:21 +0000 Subject: [PATCH 1/7] Bump default Ensembl reference version from v109 to v115 --- .../configs/GSE124530_OE_let_7c_5p.yaml | 30 +++++++++++++++ .../GSE129076_OE_miR_450a-5p_A2780.yaml | 37 +++++++++++++++++++ .../configs/gse93717.reads.example.yaml | 6 +-- pipelines/geo/geo_download.py | 8 ++-- 4 files changed, 74 insertions(+), 7 deletions(-) create mode 100644 pipelines/experiments/configs/GSE124530_OE_let_7c_5p.yaml create mode 100644 pipelines/experiments/configs/GSE129076_OE_miR_450a-5p_A2780.yaml diff --git a/pipelines/experiments/configs/GSE124530_OE_let_7c_5p.yaml b/pipelines/experiments/configs/GSE124530_OE_let_7c_5p.yaml new file mode 100644 index 00000000..b6c478f0 --- /dev/null +++ b/pipelines/experiments/configs/GSE124530_OE_let_7c_5p.yaml @@ -0,0 +1,30 @@ +dataset_id: GSE124530_OE_let_7c_5p +mirna_name: hsa-let-7c-5p +experiment_type: OE +gse: GSE124530 +source: + mode: reads + genome_fasta_path: /data1/repos/FuNmiRBench/data/experiments/raw/refs/ensembl_v115/Homo_sapiens.GRCh38.dna.primary_assembly.fa.gz + gtf_path: /data1/repos/FuNmiRBench/data/experiments/raw/refs/ensembl_v115/Homo_sapiens.GRCh38.115.gtf.gz + fastqc_threads: 8 + fastp_threads: 8 + star_threads: 16 + featurecounts_threads: 8 +comparison: + control_samples: + - sample_id: GSM3535919 + reads_1: /data1/repos/FuNmiRBench/data/experiments/raw/GSE124530/SRR8382242.fastq.gz + - sample_id: GSM3535920 + reads_1: /data1/repos/FuNmiRBench/data/experiments/raw/GSE124530/SRR8382243.fastq.gz + treated_samples: + - sample_id: GSM3535869 + reads_1: /data1/repos/FuNmiRBench/data/experiments/raw/GSE124530/SRR8382192.fastq.gz + - sample_id: GSM3535870 + reads_1: /data1/repos/FuNmiRBench/data/experiments/raw/GSE124530/SRR8382193.fastq.gz +metadata: + organism: Homo sapiens + tested_cell_line: HeLa + treatment: Overexpression of hsa-let-7c-5p + tissue: Cervix + method: RNA-seq + article_pubmed_id: https://pubmed.ncbi.nlm.nih.gov/30670076 diff --git a/pipelines/experiments/configs/GSE129076_OE_miR_450a-5p_A2780.yaml b/pipelines/experiments/configs/GSE129076_OE_miR_450a-5p_A2780.yaml new file mode 100644 index 00000000..0c10fa3a --- /dev/null +++ b/pipelines/experiments/configs/GSE129076_OE_miR_450a-5p_A2780.yaml @@ -0,0 +1,37 @@ +dataset_id: GSE129076_OE_miR_450a-5p_A2780 +mirna_name: hsa-miR-450a-5p +experiment_type: OE +gse: GSE129076 + +source: + mode: reads + genome_fasta_path: /data1/repos/FuNmiRBench/data/experiments/raw/refs/ensembl_v115/Homo_sapiens.GRCh38.dna.primary_assembly.fa.gz + gtf_path: /data1/repos/FuNmiRBench/data/experiments/raw/refs/ensembl_v115/Homo_sapiens.GRCh38.115.gtf.gz + fastqc_threads: 8 + fastp_threads: 8 + star_threads: 16 + featurecounts_threads: 8 + +comparison: + control_samples: + - sample_id: GSM3692987 + reads_1: /data1/repos/FuNmiRBench/data/experiments/raw/GSE129076/SRR8816234.fastq.gz + - sample_id: GSM3692988 + reads_1: /data1/repos/FuNmiRBench/data/experiments/raw/GSE129076/SRR8816235.fastq.gz + - sample_id: GSM3692989 + reads_1: /data1/repos/FuNmiRBench/data/experiments/raw/GSE129076/SRR8816236.fastq.gz + treated_samples: + - sample_id: GSM3692990 + reads_1: /data1/repos/FuNmiRBench/data/experiments/raw/GSE129076/SRR8816237.fastq.gz + - sample_id: GSM3692991 + reads_1: /data1/repos/FuNmiRBench/data/experiments/raw/GSE129076/SRR8816238.fastq.gz + - sample_id: GSM3692992 + reads_1: /data1/repos/FuNmiRBench/data/experiments/raw/GSE129076/SRR8816239.fastq.gz + +metadata: + organism: Homo sapiens + tested_cell_line: A2780 + treatment: Overexpression of miR-450a-5p + tissue: Ovarian + method: RNA-seq + article_pubmed_id: https://pubmed.ncbi.nlm.nih.gov/31101765/ diff --git a/pipelines/experiments/configs/gse93717.reads.example.yaml b/pipelines/experiments/configs/gse93717.reads.example.yaml index 3590e042..7a3b630a 100644 --- a/pipelines/experiments/configs/gse93717.reads.example.yaml +++ b/pipelines/experiments/configs/gse93717.reads.example.yaml @@ -6,10 +6,10 @@ gse: GSE93717 source: mode: reads - # Default: use the shared Ensembl v109 genome reference sources downloaded by + # Default: use the shared Ensembl v115 genome reference sources downloaded by # `uv run funmirbench-experiments-download-examples`. - genome_fasta_path: data/experiments/raw/refs/ensembl_v109/Homo_sapiens.GRCh38.dna.primary_assembly.fa.gz - gtf_path: data/experiments/raw/refs/ensembl_v109/Homo_sapiens.GRCh38.109.gtf.gz + genome_fasta_path: data/experiments/raw/refs/ensembl_v115/Homo_sapiens.GRCh38.dna.primary_assembly.fa.gz + gtf_path: data/experiments/raw/refs/ensembl_v115/Homo_sapiens.GRCh38.115.gtf.gz fastqc_threads: 8 fastp_threads: 8 diff --git a/pipelines/geo/geo_download.py b/pipelines/geo/geo_download.py index 27b80cf3..224b2179 100644 --- a/pipelines/geo/geo_download.py +++ b/pipelines/geo/geo_download.py @@ -57,14 +57,14 @@ FASTQ_OUTPUT_DIR = REPO_ROOT / "data/experiments/raw" CONFIG_OUTPUT_DIR = REPO_ROOT / "pipelines/experiments/configs" -# Default genome reference paths (Ensembl v109, downloaded by funmirbench-experiments-download-examples) +# Default genome reference paths (Ensembl v115, downloaded by funmirbench-experiments-download-examples) DEFAULT_GENOME_FASTA = str( - REPO_ROOT / "data/experiments/raw/refs/ensembl_v109" + REPO_ROOT / "data/experiments/raw/refs/ensembl_v115" / "Homo_sapiens.GRCh38.dna.primary_assembly.fa.gz" ) DEFAULT_GTF = str( - REPO_ROOT / "data/experiments/raw/refs/ensembl_v109" - / "Homo_sapiens.GRCh38.109.gtf.gz" + REPO_ROOT / "data/experiments/raw/refs/ensembl_v115" + / "Homo_sapiens.GRCh38.115.gtf.gz" ) REQUIRED_COUNT_MATRIX_COLUMNS = [ From 615a46817ddf0786adc57b1a8b42856b38b3bd32 Mon Sep 17 00:00:00 2001 From: Elissavet Zacharopoulou Date: Tue, 14 Jul 2026 09:22:34 +0000 Subject: [PATCH 2/7] Clean remaining perturbation label sources --- .../experiments/configs/gse129146.reads.example.yaml | 2 +- .../configs/gse253003.count_matrix.example.yaml | 2 +- pipelines/experiments/configs/gse93717.reads.example.yaml | 2 +- pipelines/geo/README.md | 8 ++++---- pipelines/geo/fetch_geo_metadata.py | 6 +++--- pipelines/geo/input_experiments.tsv | 2 +- 6 files changed, 11 insertions(+), 11 deletions(-) diff --git a/pipelines/experiments/configs/gse129146.reads.example.yaml b/pipelines/experiments/configs/gse129146.reads.example.yaml index f269f469..05882b36 100644 --- a/pipelines/experiments/configs/gse129146.reads.example.yaml +++ b/pipelines/experiments/configs/gse129146.reads.example.yaml @@ -1,6 +1,6 @@ dataset_id: GSE129146_OE_miR_455-3p mirna_name: hsa-miR-455-3p -experiment_type: OE +experiment_type: Overexpression gse: GSE129146 source: diff --git a/pipelines/experiments/configs/gse253003.count_matrix.example.yaml b/pipelines/experiments/configs/gse253003.count_matrix.example.yaml index 679eaa95..100a331a 100644 --- a/pipelines/experiments/configs/gse253003.count_matrix.example.yaml +++ b/pipelines/experiments/configs/gse253003.count_matrix.example.yaml @@ -1,6 +1,6 @@ dataset_id: GSE253003_OE_miR_323a_3p mirna_name: hsa-miR-323a-3p -experiment_type: OE +experiment_type: Overexpression gse: GSE253003 source: diff --git a/pipelines/experiments/configs/gse93717.reads.example.yaml b/pipelines/experiments/configs/gse93717.reads.example.yaml index 7a3b630a..cfeb7b34 100644 --- a/pipelines/experiments/configs/gse93717.reads.example.yaml +++ b/pipelines/experiments/configs/gse93717.reads.example.yaml @@ -1,6 +1,6 @@ dataset_id: GSE93717_OE_miR_941_deseq2 mirna_name: hsa-miR-941 -experiment_type: OE +experiment_type: Overexpression gse: GSE93717 source: diff --git a/pipelines/geo/README.md b/pipelines/geo/README.md index 2033dc2a..bc665a01 100644 --- a/pipelines/geo/README.md +++ b/pipelines/geo/README.md @@ -111,7 +111,7 @@ tested_cell_line: A549 treatment: Overexpression of miR-21-5p tissue: Lung method: RNA-seq -experiment_type: OE +experiment_type: Overexpression gse_url: https://www.ncbi.nlm.nih.gov/geo/query/acc.cgi?acc=GSE129076 raw_data_dir: (empty) control_samples: SRR8816234,SRR8816235,SRR8816236 @@ -135,7 +135,7 @@ tested_cell_line: A549 treatment: Overexpression of miR-21-5p tissue: Lung method: RNA-seq -experiment_type: OE +experiment_type: Overexpression gse_url: https://www.ncbi.nlm.nih.gov/geo/query/acc.cgi?acc=GSE129076 raw_data_dir: (empty) control_samples: GSM6437108,GSM6437109,GSM6437110 @@ -158,7 +158,7 @@ tested_cell_line: HaCaT treatment: Knockdown of miR-155-5p tissue: Skin method: RNA-seq -experiment_type: KO +experiment_type: Knockdown gse_url: https://www.ncbi.nlm.nih.gov/geo/query/acc.cgi?acc=GSE999999 raw_data_dir: /path/to/your/fastq/files control_samples: ctrl_rep1,ctrl_rep2,ctrl_rep3 @@ -187,7 +187,7 @@ tested_cell_line: HSVSMC treatment: Overexpression of miR-323-3p tissue: Vascular method: RNA-seq -experiment_type: OE +experiment_type: Overexpression gse_url: https://www.ncbi.nlm.nih.gov/geo/query/acc.cgi?acc=GSE253003 raw_data_dir: (empty) control_samples: HSVSMC_IP_miRCTRL_1,HSVSMC_IP_miRCTRL_2,HSVSMC_IP_miRCTRL_3 diff --git a/pipelines/geo/fetch_geo_metadata.py b/pipelines/geo/fetch_geo_metadata.py index 737f4595..07e2520e 100644 --- a/pipelines/geo/fetch_geo_metadata.py +++ b/pipelines/geo/fetch_geo_metadata.py @@ -356,7 +356,7 @@ def call_gemini( {{ "mirna_name": "exact miRBase mature name (e.g. hsa-miR-21-5p) or null", - "experiment_type": "OE or KO or null", + "experiment_type": "Overexpression, Knockout, Knockdown, or null", "treatment": "short description of the experimental treatment or null", "tested_cell_line": "cell line name without trailing 'cells' or 'cell line' (e.g. HaCaT, A549) or null", "tissue": "tissue or organ type (e.g. Lung, Skin, Ovarian) or null", @@ -365,7 +365,7 @@ def call_gemini( Extraction rules: - mirna_name: Use exact miRBase mature miRNA format with organism prefix and arm suffix (e.g. hsa-miR-21-5p). If the arm (-3p/-5p) is ambiguous, pick the more likely one based on context. Return null if no specific miRNA is mentioned. -- experiment_type: "OE" for overexpression/mimic/gain-of-function, "KO" for knockdown/inhibition/knockout/antagomir/loss-of-function. Return null if unclear. +- experiment_type: "Overexpression" for overexpression/mimic/gain-of-function, "Knockout" for knockout, and "Knockdown" for knockdown/inhibition/antagomir/loss-of-function. Return null if unclear. - treatment: Short phrase describing what was done (e.g. "Overexpression of miR-21-5p in HaCaT cells"). - tested_cell_line: Clean name without "cells" or "cell line" suffix. - tissue: The tissue/organ this cell line originates from or the tissue type studied. @@ -612,7 +612,7 @@ def print_summary( "mirna_name": "exact miRBase mature name (e.g. hsa-miR-21-5p, NOT hsa-mir-21-5p)\n" " wrong arm (-3p/-5p) will break downstream analysis\n" " verify at https://mirbase.org", - "experiment_type": "OE (overexpression) or KO (knockdown/inhibition/knockout)", + "experiment_type": "Overexpression, Knockout, or Knockdown", "treatment": "short description of the experiment", } for field in manual_fields: diff --git a/pipelines/geo/input_experiments.tsv b/pipelines/geo/input_experiments.tsv index 51f628db..6f28a46c 100644 --- a/pipelines/geo/input_experiments.tsv +++ b/pipelines/geo/input_experiments.tsv @@ -1,2 +1,2 @@ id mirna_name article_pubmed_id organism tested_cell_line treatment tissue method experiment_type gse_url raw_data_dir control_samples condition_samples count_matrix_path gene_id_column -GSE129076_OE_miR_450a-5p_A2780 hsa-miR-450a-5p https://pubmed.ncbi.nlm.nih.gov/31101765/ Homo sapiens A2780 Overexpression of miR-450a-5p Ovarian RNA-seq OE https://www.ncbi.nlm.nih.gov/geo/query/acc.cgi?acc=GSE129076 GSM3692987,GSM3692988,GSM3692989 GSM3692990,GSM3692991,GSM3692992 +GSE129076_OE_miR_450a-5p_A2780 hsa-miR-450a-5p https://pubmed.ncbi.nlm.nih.gov/31101765/ Homo sapiens A2780 Overexpression of miR-450a-5p Ovarian RNA-seq Overexpression https://www.ncbi.nlm.nih.gov/geo/query/acc.cgi?acc=GSE129076 GSM3692987,GSM3692988,GSM3692989 GSM3692990,GSM3692991,GSM3692992 From 654aa445bf1ea1c12ec1730f7cc3336809e32d91 Mon Sep 17 00:00:00 2001 From: Stavros Giannoukakos Date: Mon, 27 Jul 2026 11:16:10 +0000 Subject: [PATCH 3/7] Fix stale Ensembl v109 references to v115 in READMEs The downloader and geo_download.py defaults already moved to v115; the README text still described v109. --- README.md | 6 +++--- pipelines/geo/README.md | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 1b4272b8..187c31d7 100644 --- a/README.md +++ b/README.md @@ -124,7 +124,7 @@ That downloader fetches: - the real `GSE253003` count matrix - the real `GSE93717` FASTQ files -- the shared Homo sapiens Ensembl v109 genome FASTA and GTF used by the reads example +- the shared Homo sapiens Ensembl v115 genome FASTA and GTF used by the reads example Run the real count-matrix example: @@ -154,8 +154,8 @@ So the practical reads flow is: 2. run `uv run funmirbench-experiments-download-examples` 3. run `uv run funmirbench-experiments --config pipelines/experiments/configs/gse93717.reads.example.yaml` -The shipped reads example now points at the downloaded Ensembl v109 reference source files under -`data/experiments/raw/refs/ensembl_v109/`, so it builds the derived STAR index automatically. +The shipped reads example now points at the downloaded Ensembl v115 reference source files under +`data/experiments/raw/refs/ensembl_v115/`, so it builds the derived STAR index automatically. Each run writes: diff --git a/pipelines/geo/README.md b/pipelines/geo/README.md index bc665a01..df7d402d 100644 --- a/pipelines/geo/README.md +++ b/pipelines/geo/README.md @@ -240,7 +240,7 @@ Key options: The YAML is auto-generated from the TSV and uses sensible defaults, but you should verify and adjust the following before proceeding: -- **Genome reference paths** — the defaults point to Ensembl v109 (GRCh38). If your +- **Genome reference paths** — the defaults point to Ensembl v115 (GRCh38). If your experiment uses a different genome or Ensembl version, update `genome_fasta_path` and `gtf_path` accordingly. - **Thread counts** — `fastqc_threads`, `fastp_threads`, `star_threads`, and From 770e26f42fad5d5b281a08a0ee53c3b1d3bbbfe1 Mon Sep 17 00:00:00 2001 From: Stavros Giannoukakos Date: Mon, 27 Jul 2026 11:16:51 +0000 Subject: [PATCH 4/7] Add GEO pipeline lead-in and RNA-seq DE schema notes to main README Links the GEO download pipeline into the main workflow docs, and pulls in the RNA-seq pipeline summary and canonical DE schema notes that main already documents but this branch's README predates. --- README.md | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/README.md b/README.md index 187c31d7..da490cd7 100644 --- a/README.md +++ b/README.md @@ -87,6 +87,12 @@ and selects 3 real experiment datasets plus 4 demo predictors and TargetScan. ### 1. Add Experiment Data +Raw experiment data (FASTQs or a pre-existing count matrix) can be fetched directly from GEO and +turned into a ready-to-review YAML config automatically — see the dedicated +[GEO download pipeline](pipelines/geo/README.md) for the full GEO → YAML workflow. Once you have a +config, either from that pipeline or written by hand, the steps below run the RNA-seq processing +(QC/trim/align/count or count-matrix DESeq2) that produces the DE table. + The experiment-ingestion pipeline creates DE tables under `data/experiments/processed/` for local workflow use. @@ -111,6 +117,15 @@ Supported inputs: - count matrix: counts matrix + control columns + treated columns -> DESeq2 - reads: local FASTQs + local reference files + explicit sample groups -> `FastQC + fastp + STAR + featureCounts + DESeq2` +RNA-seq pipeline summary: + +- `count_matrix` mode validates the configured count matrix and runs DESeq2 directly on the selected + control and treated columns. +- `reads` mode runs read QC/trimming, aligns reads to the configured reference with STAR, counts + genes with featureCounts, then runs the same DESeq2 step. +- DE outputs preserve the original method-level `PValue` and `FDR` values. Benchmarking derives + `benchmark_FDR` and `plot_FDR` internally without modifying those RNA-seq outputs. + This path expects the `funmirbench-experiments` environment from `pipelines/experiments/environment.yml` to be active so `fastqc`, `fastp`, `STAR`, `featureCounts`, and `Rscript` are available on `PATH`. @@ -163,6 +178,24 @@ Each run writes: - `pipelines/experiments/runs/_/candidate_metadata.tsv` - `pipelines/experiments/runs/_/run_manifest.json` +The processed DE TSV keeps `PValue` and `FDR` unchanged from the DE method, including missing +adjusted p-values and exact zero values. During benchmarking, rows with `PValue` but no adjusted +p-value get `benchmark_FDR = 1`, so they remain non-significant background genes. Rows with both +`PValue` and `FDR` missing remain excluded from FDR-thresholded evaluation. Rows with `FDR = 0` +use the smallest positive floating-point value for `plot_FDR`, computed with `np.nextafter(0, 1)`, +for finite `-log10` plotting while keeping `benchmark_FDR = 0`. + +Benchmark DE tables use a canonical schema independent of the DE method: + +- `gene_id`: Ensembl gene identifier +- `logFC`: signed log fold change +- `FDR`: adjusted p-value or q-value used for FDR-thresholded evaluation +- `PValue`: optional raw p-value used to classify rows with missing adjusted p-values + +Common native headers are normalized when benchmark tables are read. For example, `log2FoldChange` +maps to `logFC`, `padj`, `adj.P.Val`, and `qvalue` map to `FDR`, and `pvalue` or `P.Value` map to +`PValue`. + The reads example uses a reproduced dataset id, `GSE93717_OE_miR_941_deseq2`, so syncing it creates a separate variant instead of overwriting the curated `GSE93717_OE_miR_941` registry row. From 19e1b3c5d0ec3fc06d012503ede3cae8a85d4c8a Mon Sep 17 00:00:00 2001 From: Stavros Giannoukakos Date: Mon, 27 Jul 2026 11:19:32 +0000 Subject: [PATCH 5/7] Document control_mean_normalized_count in canonical DE schema Per the RNA-seq pipeline maintainer. --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index da490cd7..aa4f35b5 100644 --- a/README.md +++ b/README.md @@ -190,6 +190,7 @@ Benchmark DE tables use a canonical schema independent of the DE method: - `gene_id`: Ensembl gene identifier - `logFC`: signed log fold change - `FDR`: adjusted p-value or q-value used for FDR-thresholded evaluation +- `control_mean_normalized_count`: mean of the DESeq2-normalized counts across the control samples - `PValue`: optional raw p-value used to classify rows with missing adjusted p-values Common native headers are normalized when benchmark tables are read. For example, `log2FoldChange` From f1a2223429461c3312421a83187da916074d6445 Mon Sep 17 00:00:00 2001 From: Stavros Giannoukakos Date: Mon, 27 Jul 2026 12:50:18 +0000 Subject: [PATCH 6/7] Add dedicated experiment ingestion pipeline README Mirrors the GEO download pipeline README's format: overview diagram, numbered steps, output schema, and an outputs table. --- pipelines/experiments/README.md | 176 ++++++++++++++++++++++++++++++++ 1 file changed, 176 insertions(+) create mode 100644 pipelines/experiments/README.md diff --git a/pipelines/experiments/README.md b/pipelines/experiments/README.md new file mode 100644 index 00000000..f86403f6 --- /dev/null +++ b/pipelines/experiments/README.md @@ -0,0 +1,176 @@ +# Experiment Ingestion Pipeline + +This pipeline turns raw experiment data (a pre-existing count matrix or FASTQs) into a +benchmark-ready differential-expression (DE) table under `data/experiments/processed/`, using +DESeq2 (`funmirbench/experiments_pipeline.py`). It is typically the second stage of the full +experiment workflow, after the [GEO download pipeline](../geo/README.md) has produced a YAML +config — though a config can also be written by hand. + +--- + +## Overview of the full pipeline + +``` +0. (Optional) Run the GEO download pipeline → auto-generates a YAML config + ↓ +1. Review / write pipelines/experiments/configs/{dataset_id}.yaml + ↓ +2. Run funmirbench-experiments --config ... → data/experiments/processed/{dataset_id}.tsv + ↓ +3. Run funmirbench-sync-metadata → upserts row into metadata/mirna_experiment_info.tsv +``` + +--- + +## Step 0 (Optional) - Acquire data from GEO + +Raw FASTQs or a count matrix, plus a ready-to-review YAML config, can be generated automatically +from a GEO accession. See the [GEO download pipeline](../geo/README.md) for the full workflow. + +## Step 1 - Write or review the YAML config + +Experiment config summary: + +- top-level: + `dataset_id`, `mirna_name`, `experiment_type`, optional `gse` +- `source`: + `mode: count_matrix` or `mode: reads` +- `comparison`: + control vs treated columns or explicit control vs treated samples +- `metadata`: + fields that will later be synced into `metadata/mirna_experiment_info.tsv` + +Supported inputs: + +- count matrix: counts matrix + control columns + treated columns -> DESeq2 +- reads: local FASTQs + local reference files + explicit sample groups -> `FastQC + fastp + STAR + featureCounts + DESeq2` + +Tracked example configs: + +- `pipelines/experiments/configs/gse253003.count_matrix.example.yaml` +- `pipelines/experiments/configs/gse93717.reads.example.yaml` + +Reads configs can either: + +- use local `reads_1` and optional `reads_2` +- use local `genome_fasta_path` and `gtf_path` + +--- + +## Step 2 - Set up the environment + +```bash +conda env create -f pipelines/experiments/environment.yml +conda activate funmirbench-experiments +``` + +That environment also includes `uv`, so `uv run ...` keeps working after activation, and provides +`fastqc`, `fastp`, `STAR`, `featureCounts`, and `Rscript` on `PATH`. + +--- + +## Step 3 - Run the pipeline + +RNA-seq pipeline summary: + +- `count_matrix` mode validates the configured count matrix and runs DESeq2 directly on the selected + control and treated columns. +- `reads` mode runs read QC/trimming, aligns reads to the configured reference with STAR, counts + genes with featureCounts, then runs the same DESeq2 step. +- DE outputs preserve the original method-level `PValue` and `FDR` values. Benchmarking derives + `benchmark_FDR` and `plot_FDR` internally without modifying those RNA-seq outputs. + +Download the shipped real example inputs: + +```bash +uv run funmirbench-experiments-download-examples +``` + +That downloader fetches: + +- the real `GSE253003` count matrix +- the real `GSE93717` FASTQ files +- the shared Homo sapiens Ensembl v115 genome FASTA and GTF used by the reads example + +Run the real count-matrix example: + +```bash +uv run funmirbench-experiments --config pipelines/experiments/configs/gse253003.count_matrix.example.yaml +``` + +Run the reads example the same way: + +```bash +uv run funmirbench-experiments --config pipelines/experiments/configs/gse93717.reads.example.yaml +``` + +So the practical reads flow is: + +1. activate `funmirbench-experiments` +2. run `uv run funmirbench-experiments-download-examples` +3. run `uv run funmirbench-experiments --config pipelines/experiments/configs/gse93717.reads.example.yaml` + +The shipped reads example now points at the downloaded Ensembl v115 reference source files under +`data/experiments/raw/refs/ensembl_v115/`, so it builds the derived STAR index automatically. + +Each run writes: + +- `data/experiments/processed/.tsv` +- `pipelines/experiments/runs/_/candidate_metadata.tsv` +- `pipelines/experiments/runs/_/run_manifest.json` + +The reads example uses a reproduced dataset id, `GSE93717_OE_miR_941_deseq2`, so syncing it creates +a separate variant instead of overwriting the curated `GSE93717_OE_miR_941` registry row. + +### Output DE table schema + +The processed DE TSV keeps `PValue` and `FDR` unchanged from the DE method, including missing +adjusted p-values and exact zero values. During benchmarking, rows with `PValue` but no adjusted +p-value get `benchmark_FDR = 1`, so they remain non-significant background genes. Rows with both +`PValue` and `FDR` missing remain excluded from FDR-thresholded evaluation. Rows with `FDR = 0` +use the smallest positive floating-point value for `plot_FDR`, computed with `np.nextafter(0, 1)`, +for finite `-log10` plotting while keeping `benchmark_FDR = 0`. + +Benchmark DE tables use a canonical schema independent of the DE method: + +- `gene_id`: Ensembl gene identifier +- `logFC`: signed log fold change +- `FDR`: adjusted p-value or q-value used for FDR-thresholded evaluation +- `control_mean_normalized_count`: mean of the DESeq2-normalized counts across the control samples +- `PValue`: optional raw p-value used to classify rows with missing adjusted p-values + +Common native headers are normalized when benchmark tables are read. For example, `log2FoldChange` +maps to `logFC`, `padj`, `adj.P.Val`, and `qvalue` map to `FDR`, and `pvalue` or `P.Value` map to +`PValue`. + +--- + +## Step 4 - Sync into the experiment registry + +The ingestion pipeline does not edit `metadata/mirna_experiment_info.tsv` by itself. It writes a +`candidate_metadata.tsv` under `pipelines/experiments/runs/_/` first. +Then sync it into the registry with: + +```bash +uv run funmirbench-sync-metadata +``` + +That command auto-discovers all `candidate_metadata.tsv` files under `pipelines/experiments/runs/` +and upserts them into the registry. Re-running is safe — existing rows with matching `id` values are +replaced, not duplicated. + +To sync a specific file instead: + +```bash +uv run funmirbench-sync-metadata --input pipelines/experiments/runs//candidate_metadata.tsv +``` + +--- + +## Outputs + +| Path | Description | +|---|---| +| `data/experiments/processed/.tsv` | Final DE table | +| `pipelines/experiments/runs/_/candidate_metadata.tsv` | Registry row candidate, synced via `funmirbench-sync-metadata` | +| `pipelines/experiments/runs/_/run_manifest.json` | Run manifest (commands, inputs, timestamps) | From 0d32d492e33c2357c773d50f56a58bb387d9fa79 Mon Sep 17 00:00:00 2001 From: Stavros Giannoukakos Date: Mon, 27 Jul 2026 12:50:25 +0000 Subject: [PATCH 7/7] Slim main README experiment section and link to dedicated pipeline docs Moves detailed RNA-seq ingestion mechanics into pipelines/experiments/README.md and leaves a brief pointer in the main README. Renumbers the remaining Workflow steps and repoints the GEO README's step 5 at the new dedicated doc. --- README.md | 139 ++++------------------------------------ pipelines/geo/README.md | 5 +- 2 files changed, 14 insertions(+), 130 deletions(-) diff --git a/README.md b/README.md index aa4f35b5..17349306 100644 --- a/README.md +++ b/README.md @@ -87,140 +87,23 @@ and selects 3 real experiment datasets plus 4 demo predictors and TargetScan. ### 1. Add Experiment Data -Raw experiment data (FASTQs or a pre-existing count matrix) can be fetched directly from GEO and -turned into a ready-to-review YAML config automatically — see the dedicated -[GEO download pipeline](pipelines/geo/README.md) for the full GEO → YAML workflow. Once you have a -config, either from that pipeline or written by hand, the steps below run the RNA-seq processing -(QC/trim/align/count or count-matrix DESeq2) that produces the DE table. +Experiment DE tables are produced by a dedicated ingestion pipeline that runs DESeq2 on a count +matrix or on FASTQs (via FastQC + fastp + STAR + featureCounts), then syncs the result into +`metadata/mirna_experiment_info.tsv`. Raw data can also be fetched directly from GEO and turned +into a ready-to-review YAML config automatically. See the dedicated pipelines for the full +workflow: -The experiment-ingestion pipeline creates DE tables under `data/experiments/processed/` for local -workflow use. +- [GEO download pipeline](pipelines/geo/README.md) — fetch FASTQs/count matrices from GEO and + auto-generate a YAML config +- [Experiment ingestion pipeline](pipelines/experiments/README.md) — run DESeq2 (count matrix or + reads mode) and sync results into the registry For the curated benchmark datasets tracked in `metadata/mirna_experiment_info.tsv`, the expected workflow is different: those metadata rows stay versioned in the repo, and the corresponding DE tables live under the local `data/experiments/processed/18745741/` cache. The repo currently ships the 3 default benchmark TSVs there, and other curated tables are fetched from Zenodo when needed. -Experiment config summary: - -- top-level: - `dataset_id`, `mirna_name`, `experiment_type`, optional `gse` -- `source`: - `mode: count_matrix` or `mode: reads` -- `comparison`: - control vs treated columns or explicit control vs treated samples -- `metadata`: - fields that will later be synced into `metadata/mirna_experiment_info.tsv` - -Supported inputs: - -- count matrix: counts matrix + control columns + treated columns -> DESeq2 -- reads: local FASTQs + local reference files + explicit sample groups -> `FastQC + fastp + STAR + featureCounts + DESeq2` - -RNA-seq pipeline summary: - -- `count_matrix` mode validates the configured count matrix and runs DESeq2 directly on the selected - control and treated columns. -- `reads` mode runs read QC/trimming, aligns reads to the configured reference with STAR, counts - genes with featureCounts, then runs the same DESeq2 step. -- DE outputs preserve the original method-level `PValue` and `FDR` values. Benchmarking derives - `benchmark_FDR` and `plot_FDR` internally without modifying those RNA-seq outputs. - -This path expects the `funmirbench-experiments` environment from `pipelines/experiments/environment.yml` to be -active so `fastqc`, `fastp`, `STAR`, `featureCounts`, and `Rscript` are available on `PATH`. - -Download the shipped real example inputs: - -```bash -uv run funmirbench-experiments-download-examples -``` - -That downloader fetches: - -- the real `GSE253003` count matrix -- the real `GSE93717` FASTQ files -- the shared Homo sapiens Ensembl v115 genome FASTA and GTF used by the reads example - -Run the real count-matrix example: - -```bash -uv run funmirbench-experiments --config pipelines/experiments/configs/gse253003.count_matrix.example.yaml -``` - -Run the reads example the same way: - -```bash -uv run funmirbench-experiments --config pipelines/experiments/configs/gse93717.reads.example.yaml -``` - -Tracked example configs: - -- `pipelines/experiments/configs/gse253003.count_matrix.example.yaml` -- `pipelines/experiments/configs/gse93717.reads.example.yaml` - -Reads configs can either: - -- use local `reads_1` and optional `reads_2` -- use local `genome_fasta_path` and `gtf_path` - -So the practical reads flow is: - -1. activate `funmirbench-experiments` -2. run `uv run funmirbench-experiments-download-examples` -3. run `uv run funmirbench-experiments --config pipelines/experiments/configs/gse93717.reads.example.yaml` - -The shipped reads example now points at the downloaded Ensembl v115 reference source files under -`data/experiments/raw/refs/ensembl_v115/`, so it builds the derived STAR index automatically. - -Each run writes: - -- `data/experiments/processed/.tsv` -- `pipelines/experiments/runs/_/candidate_metadata.tsv` -- `pipelines/experiments/runs/_/run_manifest.json` - -The processed DE TSV keeps `PValue` and `FDR` unchanged from the DE method, including missing -adjusted p-values and exact zero values. During benchmarking, rows with `PValue` but no adjusted -p-value get `benchmark_FDR = 1`, so they remain non-significant background genes. Rows with both -`PValue` and `FDR` missing remain excluded from FDR-thresholded evaluation. Rows with `FDR = 0` -use the smallest positive floating-point value for `plot_FDR`, computed with `np.nextafter(0, 1)`, -for finite `-log10` plotting while keeping `benchmark_FDR = 0`. - -Benchmark DE tables use a canonical schema independent of the DE method: - -- `gene_id`: Ensembl gene identifier -- `logFC`: signed log fold change -- `FDR`: adjusted p-value or q-value used for FDR-thresholded evaluation -- `control_mean_normalized_count`: mean of the DESeq2-normalized counts across the control samples -- `PValue`: optional raw p-value used to classify rows with missing adjusted p-values - -Common native headers are normalized when benchmark tables are read. For example, `log2FoldChange` -maps to `logFC`, `padj`, `adj.P.Val`, and `qvalue` map to `FDR`, and `pvalue` or `P.Value` map to -`PValue`. - -The reads example uses a reproduced dataset id, `GSE93717_OE_miR_941_deseq2`, so syncing it creates -a separate variant instead of overwriting the curated `GSE93717_OE_miR_941` registry row. - -### 2. Sync Experiment Metadata - -The ingestion pipeline does not edit `metadata/mirna_experiment_info.tsv` by itself. It writes a -`candidate_metadata.tsv` under `pipelines/experiments/runs/_/` first. -Then sync it into the registry with: - -```bash -uv run funmirbench-sync-metadata -``` - -That command auto-discovers all `candidate_metadata.tsv` files under `pipelines/experiments/runs/` -and upserts them into the registry. Re-running is safe — existing rows with matching `id` values are -replaced, not duplicated. - -To sync a specific file instead: - -```bash -uv run funmirbench-sync-metadata --input pipelines/experiments/runs//candidate_metadata.tsv -``` - -### 3. Add Predictor Data +### 2. Add Predictor Data Predictor score files live under `data/predictions/` and are discovered through `metadata/predictions_info.tsv`. @@ -253,7 +136,7 @@ that those build thresholds match the current `evaluation` config before running The demo predictors already have registry rows in `metadata/predictions_info.tsv`. -### 4. Run The Benchmark +### 3. Run The Benchmark The default benchmark config is `benchmark.yaml`. diff --git a/pipelines/geo/README.md b/pipelines/geo/README.md index df7d402d..14284bd2 100644 --- a/pipelines/geo/README.md +++ b/pipelines/geo/README.md @@ -260,8 +260,9 @@ pipelines/experiments/configs/{dataset_id}.yaml ## Step 5 - Run the RNA-seq pipeline -Once the YAML config is reviewed and ready, refer to the [main project README](../../README.md) -for instructions on running the RNA-seq pipeline (`funmirbench/experiments_pipeline.py`). +Once the YAML config is reviewed and ready, refer to the +[experiment ingestion pipeline README](../experiments/README.md) for instructions on running the +RNA-seq pipeline (`funmirbench/experiments_pipeline.py`). ---