WulfRNA is a packaged CLI for a focused bulk RNA-seq workflow on paired-end (default) or single-end FASTQ input.
Current outputs:
- source-qualified, gene-level expected counts and TPM from Salmon or kallisto
- optional STAR count and WulfRNA-calculated gene-level TPM matrices
- optional coordinate-sorted STAR BAM and BAI
- STAR splice-junction and gene-count outputs
- final MultiQC report
Pipeline steps: FastQC (raw) → Cutadapt → FastQC (trimmed) → optional STAR alignment → transcript quantification (Salmon or kallisto) → gene-level aggregation → MultiQC.
Public-readiness note: WulfRNA v0.2.4 is a lightweight single-server bulk RNA-seq runner intended for local or HPC workstation use.
WulfRNA does not install analysis binaries for you. They must already be installed and visible in PATH at runtime.
Required commands:
bashpython3fastqccutadaptmultiqcsalmon(default backend) orkallisto(optional backend, when selected)STARandsamtools(optional, required only when--aligner staris selected)
Useful standard utilities expected on Linux nodes:
gzip,zcat,awk,sed,grep,sort,head,tail
Use Python 3.10+ and a virtual environment:
python3 -m venv .venv
source .venv/bin/activate
pip install .This installs the wulfrna command.
WORKDIR must contain fastq/ and uses an explicit input layout:
sample_id_R1.fastq.gzsample_id_R2.fastq.gz
sample_id.fastq.gzorsample_id_R1.fastq.gz*_R2.fastq.gzfiles are not allowed in single-end mode (run fails if present).
--reference must point to a directory containing backend-specific resources plus a shared tx2gene map:
- shared:
combined_tx2gene.tsv - shared:
combined_gene_annotation.tsv, with columnsgene_id,GeneName, and positive integergene_length_bp(the union length of annotated exons, counting overlaps once) - Salmon backend:
salmon_index/ - kallisto backend:
kallisto_index/combined_transcripts.kidx - STAR aligner (when
--aligner star):star_index/containing non-emptyGenome,SA,SAindex,genomeParameters.txt,chrName.txt,chrLength.txt, andchrNameLength.txt
Generate combined_gene_annotation.tsv from the same GTF used to build the
STAR index and combined_tx2gene.tsv:
python scripts/build_gene_annotation.py \
--gtf /path/to/combined.gtf \
--output /path/to/reference/combined_gene_annotation.tsvThe builder reads exon records, preserves each GTF gene_id exactly, merges
overlapping or adjacent exon intervals within a gene, and writes their union
length as gene_length_bp. It uses gene_name for GeneName and writes NA
when no symbol exists. A gene assigned to multiple chromosomes, inconsistent
gene names, malformed records, or invalid coordinates cause a clear failure.
Use the identical combined GTF for all reference artifacts so gene IDs match
between this table, combined_tx2gene.tsv, and STAR.
wulfrna run WORKDIR --reference /path/to/reference --stranded reverse --threads 16 \
--adapter-r1 R1_SEQUENCE --adapter-r2 R2_SEQUENCER1_SEQUENCE and R2_SEQUENCE are placeholders. Replace them with the regular
3′ adapter sequences specified by the library preparation protocol.
Arguments:
WORKDIR(positional): working directory containingfastq/--reference PATH(required): prepared reference directory--stranded {none|forward|reverse}(required): library strandedness- Salmon mapping:
none -> IU,forward -> ISF,reverse -> ISR - kallisto mapping:
none -> (unstranded default),forward -> --fr-stranded,reverse -> --rf-stranded
- Salmon mapping:
--threads N(required): total threads (N >= 1)--quantifier {salmon|kallisto}(optional, defaultsalmon)--aligner {none|star}(optional, defaultnone): run STAR alignment from trimmed FASTQs and write isolated alignment outputs underalign/star/<sample>/; Salmon/kallisto quantification and abundance matrices are still produced normally--single-end,--SE(optional): switch layout frompaired_endtosingle_end--adapter-r1 SEQUENCE(repeatable): regular 3′ adapter candidate for read 1--adapter-r2 SEQUENCE(repeatable, paired-end only): regular 3′ adapter candidate for read 2--no-adapter-trimming: skip adapter removal while retaining the nonempty-read safety filter--fragment-length FLOATand--fragment-sd FLOAT(single-end kallisto only; both required and must be> 0)--min-mapping-rate FLOAT(optional, default0.90): minimum acceptable tx2gene transcript mapping rate per sample (0.0-1.0)--dry-run(optional): validate tools/reference/inputs, write separate dry-run metadata/status, then exit--genome NAME(optional): resolve references as<reference>/<NAME>/...--no-resume(optional): disable phase-level resume and rerun all phases--force-from {fastqc_raw,cutadapt,fastqc_trimmed,align,quant,aggregate,multiqc}(optional): force rerun from the selected phase onward
Backward-compatibility note: legacy invocation without explicit run is still accepted, but wulfrna run ... is the intended interface.
Every run must choose exactly one explicit trimming strategy:
- Paired-end: provide at least one
--adapter-r1and at least one--adapter-r2. - Single-end: provide at least one
--adapter-r1;--adapter-r2is rejected. - Intentional adapter-free processing: provide
--no-adapter-trimmingand no adapter sequences.
Repeat an adapter option to test multiple protocol-appropriate candidates:
wulfrna run WORKDIR --reference REFDIR --stranded reverse --threads 8 \
--adapter-r1 R1_SEQUENCE_1 --adapter-r1 R1_SEQUENCE_2 \
--adapter-r2 R2_SEQUENCE_1 --adapter-r2 R2_SEQUENCE_2Single-end example:
wulfrna run WORKDIR --reference REFDIR --stranded reverse --threads 8 \
--single-end --adapter-r1 R1_SEQUENCESequences are case-normalized and must contain only supported IUPAC DNA codes. Advanced Cutadapt expressions, linked/anchored adapters, and presets are not supported. Choose sequences from the library preparation protocol: a FastQC adapter label does not establish the correct complete sequence, and WulfRNA does not silently substitute a generic Illumina or Nextera adapter.
Cutadapt always applies --minimum-length 1 after adapter processing, including
with --no-adapter-trimming. Paired-end runs also use --pair-filter=any, so
an entire pair is discarded when either mate is empty. This keeps retained R1
and R2 records synchronized and prevents zero-length reads from reaching STAR.
--no-adapter-trimming disables adapter matching only; it does not disable this
safety filter.
Migration requirement: runs that previously omitted adapter options must now
provide explicit sequences or --no-adapter-trimming. Existing work directories
whose manifests do not contain verified trimming metadata are invalidated from
Cutadapt onward; raw FastQC output remains reusable.
v0.2.4 migration: v0.2.3 and older manifests do not record the nonempty-read
policy. On the first v0.2.4 execution, WulfRNA automatically invalidates
Cutadapt and all downstream phases while preserving raw FastQC. A dry-run only
reports this plan. To request the same rebuild explicitly, use
--force-from cutadapt.
pip install -e .
wulfrna --help
wulfrna run <workdir> --reference <reference_dir> --stranded reverse --threads 4 --no-adapter-trimming --dry-run
wulfrna run <workdir> --reference <reference_dir> --stranded reverse --threads 4 --quantifier kallisto --no-adapter-trimming --dry-run
wulfrna run <workdir> --reference <reference_dir> --stranded reverse --threads 4 --aligner star --no-adapter-trimming --dry-runNotes:
- These smoke commands use
--no-adapter-trimmingintentionally to validate setup only; production runs should use protocol-specific adapter sequences when removal is required. - For dry-run to pass, required binaries must be in
PATH, references must be complete for the selected quantifier and optional aligner, and<workdir>/fastqmust contain valid FASTQ inputs for the selected layout (paired_endorsingle_end). A dry run reports resume invalidation without replacing the authoritative execution manifest, status,logs/run_parameters.txt, ormetadata/versions.txt; its invocation and versions are written tologs/dry_run_parameters.txtandmetadata/dry_run_versions.txt, and its status is written understatus/dry_run/. - Single-end examples:
- Salmon:
wulfrna run WORKDIR --reference REFDIR --stranded reverse --threads 4 --single-end --adapter-r1 R1_SEQUENCE --dry-run - kallisto:
wulfrna run WORKDIR --reference REFDIR --stranded reverse --threads 4 --single-end --quantifier kallisto --fragment-length 200 --fragment-sd 20 --adapter-r1 R1_SEQUENCE --dry-run
- Salmon:
Expected primary outputs on full success:
abundance/<quantifier>_gene_expected_counts.tsvabundance/<quantifier>_gene_tpm.tsvabundance/gene_expected_counts.tsv(legacy v0.2.x compatibility output withoutGeneName)abundance/gene_tpm.tsv(legacy v0.2.x compatibility output withoutGeneName)multiqc/multiqc_report.htmllogs/tx2gene_mapping_stats.tsv
Additional outputs when --aligner star is selected (per sample):
align/star/<sample>/Aligned.sortedByCoord.out.bamalign/star/<sample>/Aligned.sortedByCoord.out.bam.baialign/star/<sample>/SJ.out.tabalign/star/<sample>/ReadsPerGene.out.tabalign/star/<sample>/Log.final.outabundance/star_gene_counts/<sample>.star.ReadsPerGene.out.tab(metadata-preserving copy)abundance/star_gene_counts.tsvabundance/star_gene_tpm.tsv
New matrices begin with gene_id, GeneName, then deterministically sorted sample columns. Salmon/kallisto TPM is summed from transcript-quantifier output. In contrast, star_gene_tpm.tsv is WulfRNA-calculated gene-level TPM from STAR counts using exon-union lengths from combined_gene_annotation.tsv; it is not a native STAR output. STAR's count column is selected from --stranded (none: column 2, forward: column 3, reverse: column 4). STAR TPM values are serialized with six decimal places, then each serialized sample column is required to sum to 1,000,000 within an absolute tolerance of 0.01.
Matrix behavior note:
- Gene-level matrices include only genes observed in the transcript quantification input (unobserved zero-only genes are not emitted).
Status files in WORKDIR/status/:
- during run:
RUNNING - full success:
SUCCESS,finished_at.txt,summary.txt - dry-run state:
dry_run/RUNNING, thendry_run/DRY_RUN_OKordry_run/FAILED, with dry-run-specific details in the same subdirectory - failure:
FAILED,failed_step.txt(and optionallyfailed_sample.txt),summary.txt - phase checkpoint markers:
status/steps/<phase>.donefor each completed phase - run compatibility manifest:
status/manifest.json
By default, wulfrna run ... automatically resumes at the phase level (not sample-level).
Phases:
fastqc_rawcutadaptfastqc_trimmedalign(only when--aligner star)quantaggregatemultiqc
A phase is skipped only when:
status/steps/<phase>.doneexists, and- expected outputs for that phase exist and are non-empty, and
status/manifest.jsonis compatible with the current run configuration.
Conservative compatibility rules:
- If sample IDs changed: resume is blocked with an error.
- If input layout changed (
paired_endvssingle_end): automatic resume is blocked with an error. - If the adapter mode or either ordered adapter list changed, if the read-filtering policy changed, if a legacy manifest lacks trimming or read-filtering metadata, or if completed Cutadapt/downstream checkpoints have no manifest:
cutadaptand every downstream phase rerun;fastqc_rawremains reusable. - If
quantifier,reference_dir, orstrandedchanged:quantand downstream phases rerun. - If
aligneror STAR index content changed:alignand downstream phases rerun when STAR alignment is enabled. - If
combined_tx2gene.tsvfingerprint changed:aggregateandmultiqcrerun. - If
combined_gene_annotation.tsvfingerprint changed:aggregateandmultiqcrerun. - If only thread count changed: resume is allowed.
To fully disable resume:
wulfrna run WORKDIR --reference REFDIR --stranded reverse --threads 16 \
--adapter-r1 R1_SEQUENCE --adapter-r2 R2_SEQUENCE --no-resumeTo explicitly rebuild trimmed reads and all dependent outputs with the same
configuration, use --force-from cutadapt. WulfRNA clears the Cutadapt and
downstream phase markers before recording new execution provenance, so an
interrupted rerun resumes at the first incomplete phase without accepting stale
outputs.
To rerun only aggregation/reporting after fixing combined_tx2gene.tsv:
- preferred:
--force-from aggregate, or - remove aggregate + multiqc outputs and rerun.
Example:
wulfrna run WORKDIR --reference REFDIR --stranded reverse --threads 16 \
--adapter-r1 R1_SEQUENCE --adapter-r2 R2_SEQUENCE --force-from aggregateIf you use WulfRNA in your research, please cite:
Kudoh, F. (2026). WulfRNA (Version 0.2.2) [Computer software]. Zenodo. https://doi.org/10.5281/zenodo.21409117
Citation metadata is also available in CITATION.cff.
