Create your own
Lesson illustration

Uncovering Hidden Assumptions in Pipeline Structure and Metadata

Hello. In the previous lesson, you created a sample-and-asset inventory so that raw reads, derived data, code, results, and supporting files each have an explicit role. That inventory lets you ask a more demanding question: what must be true for the current pipeline to work correctly?

Many pipeline failures are not caused by an obviously broken command. They occur because a script silently assumes that every FASTQ follows one naming pattern, every sample has an R2 mate, the current directory is the project root, or a metadata label such as control is always spelled exactly the same way. A professional pipeline makes those assumptions visible, documents them, and later validates the important ones.

By the end of this lesson, you will be able to inspect your existing RNA-seq project and produce an assumption audit covering filenames, directory layout, metadata, and reference resources. This is a useful portfolio artifact: it shows that you can reason about reproducibility and failure modes, not only run tools.


An assumption is a hidden contract

An assumption is a condition your pipeline relies on without necessarily checking or documenting it.

For example, consider this Bash fragment:

for r1 in data/raw/*_R1.fastq.gz; do
  sample=$(basename "$r1" _R1.fastq.gz)
  r2="data/raw/${sample}_R2.fastq.gz"
done

This may work perfectly on your current dataset. But it embeds several contracts:

LocationImplied assumption
data/raw/All raw reads are stored directly in this directory.
*_R1.fastq.gzEvery forward-read filename ends in exactly _R1.fastq.gz.
basename ... _R1.fastq.gzEverything before that suffix is a valid sample identifier.
${sample}_R2.fastq.gzEvery sample is paired-end and has a matching R2 file.
One loop iteration per R1 fileEach FASTQ pair represents one analysis sample rather than one lane or technical run.

None of these assumptions is inherently wrong. The problem arises when it is unverified, undocumented, or false for a subset of samples.

A helpful distinction is:

  • A documented contract is an intentional rule, such as “input FASTQs must be gzip-compressed and named using the project naming convention.”
  • A hidden assumption is a rule that exists only in a filename parser, a hard-coded path, or someone’s memory.
  • A validation is a check that stops or warns when the contract is violated.

This lesson focuses on identifying the first two. You will build validations later, when you develop reliable R and Bash scripts.


Read filenames as a grammar, not as decoration

A filename often carries operational information. It may encode a sample label, sequencing lane, mate number, processing stage, date, contrast, or version. But a filename is not a reliable substitute for structured metadata.

A filename convention can combine a project name, ISO-style date, content description, version, and extension using underscores. The important point is that each component has a defined meaning and order.

A typical Illumina-derived RNA-seq filename might look like:

PRJ01_S01_L002_R1_001.fastq.gz

Depending on the facility and conversion software, the tokens often suggest:

TokenLikely meaningAssumption to verify
PRJ01Project or sequencing-batch labelIs it really stable across all data deliveries?
S01Sample-sheet position or library labelDoes it equal your biological sample ID?
L002Sequencing laneAre lanes separate technical runs that must be combined?
R1Read mate 1Is the library paired-end, and is a corresponding R2 file present?
001File split numberIs there only one split per lane, or must several files be concatenated?
.fastq.gzGzip-compressed FASTQDoes your script reject uncompressed or incorrectly named inputs?

Be particularly careful with what a label does not prove:

  • R1 and R2 identify the two mates of a paired-end fragment; they do not establish library strandedness.
  • A token such as control in a filename does not prove the sample belongs in the control group. The experimental condition belongs in metadata.
  • A prefix such as S01 may identify a library or sample-sheet position, not necessarily an independent biological replicate.
  • A filename that appears unique may still refer to one of several lanes for the same library.

The following short video gives practical principles for choosing a convention: descriptive but concise names, safe separators, sortable dates, and leading zeros for numeric order.

Knowledge clip: Keeping research data organized

Watch “Knowledge clip: Keeping research data organized” from UGent Open Science for a compact framework for deciding what belongs in a filename and what belongs in a directory.

Watch file naming to focus on informative components, sortable dates, and safe characters. Then watch directory design for the distinction between a logical hierarchy and overlapping categories.

Common filename assumptions in an RNA-seq pipeline

Audit each command in your current Bash pipeline that uses a wildcard, suffix removal, sed, awk, or parameter expansion. Look for these common assumptions:

  1. Read-pair convention
    The script may expect _R1 and _R2, while the facility supplied _1 and _2, or different extensions such as .fq.gz.

  2. One FASTQ pair equals one analysis sample
    This fails when a sample has reads from multiple lanes, multiple sequencing runs, or technical replicates.

  3. Sample IDs can be recovered from filenames without ambiguity
    A parser such as “remove everything after the first underscore” breaks when the meaningful sample ID itself contains underscores.

  4. Every library has the same layout
    A script may assume paired-end reads even though one public dataset sample is single-end, or it may assume one strandedness setting for all samples.

  5. Filename order represents biological order
    Lexical order is not experimental design. control_1, control_10, and control_2 may sort unexpectedly without leading zeros; more importantly, order should never determine condition assignment.

  6. A name indicates processing state truthfully
    A file named trimmed.fastq.gz may have been copied, partially produced, or created with different trimming parameters. A name is evidence of intent, not proof of provenance.

A particularly high-value question for your own project is:

When your script extracts a “sample name” from a FASTQ filename, is it extracting a biological sample ID, a library ID, a lane-specific run ID, or merely a convenient file stem?

Write down the answer rather than relying on an intuitive interpretation.


Lanes and repeated runs: the assumption most likely to change your sample count

Suppose your raw-read directory contains:

CTRL_01_L001_R1.fastq.gz
CTRL_01_L001_R2.fastq.gz
CTRL_01_L002_R1.fastq.gz
CTRL_01_L002_R2.fastq.gz
TRT_01_L001_R1.fastq.gz
TRT_01_L001_R2.fastq.gz

A simple filename-based pipeline might interpret this as three samples:

CTRL_01_L001
CTRL_01_L002
TRT_01_L001

But the experiment may contain only two biological samples: CTRL_01 and TRT_01, with CTRL_01 sequenced across two lanes. Treating the two control lanes as independent biological replicates would inflate apparent replication and can invalidate downstream inference.

The nf-core RNA-seq samplesheet model makes this contract explicit: multiple rows can share the same sample identifier when one sample was sequenced more than once. The workflow then handles the raw-read runs as inputs belonging to the same sample rather than treating them as independent biological observations.

rnaseq: Usage

Read the relevant parts of the nf-core RNA-seq usage documentation as a concrete example of how a mature workflow turns hidden filename and reference assumptions into explicit input requirements.

In “Samplesheet input,” read the input contract, noting the required fields and why a pipeline should not infer them solely from filenames. Continue into “Multiple runs of the same sample,” beginning with the lane handling explanation; compare its repeated sample identifier with your own lane and run naming. Then, in “Reference genome options,” read the note beginning the reference consistency note. Focus on the fact that genome and annotation filenames can conceal incompatible chromosome and gene-ID conventions.

For your project, keep these identities separate in metadata whenever the source information permits:

biological_sample_id
library_id
run_id
lane_id
analysis_sample_id

You may not know all of them for a public dataset. Record what is available and state what is unknown. Do not silently declare a one-to-one relationship merely because the filename seems to imply one.


Directory layouts make assumptions about meaning and execution

A directory tree is also a contract. It tells both humans and scripts where things are expected to live, what should be preserved, and what can be regenerated.

A project hierarchy separates data, scripts, and outputs, then subdivides data into input, intermediate, and analysis-ready material. Such a layout makes roles visible, but only if each directory has a clear definition.

A well-organized layout is not mainly about aesthetic neatness. It limits dangerous ambiguity. Consider these directory names:

data/
results/
output/
final/
new/
processed/

They invite questions:

  • Is processed/ an alignment directory, a normalized count table, or a cleaned metadata file?
  • Are results/ and output/ different categories, or do they contain duplicate figures?
  • Does final/ mean reviewed and reproducible, or simply “the version I last edited”?
  • Can a script safely delete and recreate output/?
  • Does data/ include immutable raw FASTQs, downloaded references, and derived count matrices together?

A more meaningful distinction is based on role and mutability:

Directory roleTypical contentsContract to document
Raw inputOriginal FASTQs or download manifestsNever modify in place.
Reference inputFASTA, GTF, indices, reference manifestVersions must match and be recorded.
Metadata/configurationSample sheet, contrast definition, parametersValues are human-reviewed and machine-readable.
CodeBash, R, reporting, and test scriptsVersion-controlled; scripts use project-relative paths.
Derived dataBAMs, quantifications, count matricesRegenerable from specified inputs and code.
ResultsQC reports, figures, DE tables, report outputGenerated from a documented run; not hand-edited.
LogsCommands, timestamps, warnings, tool versionsPreserve evidence of what actually ran.

The exact folder names can differ. What matters is that a given category has one clear home and that a file should not reasonably fit in several competing places.

How to organize a bioinformatics project: using bash to set up a project directory (CC013)

Watch “How to organize a bioinformatics project: using bash to set up a project directory (CC013)” from the Riffomonas Project for a practical explanation of self-contained project structure and project-root execution.

Watch organization principles. Focus on the separation of raw inputs, derived outputs, code, and references, and on the convention of launching work from the project root. Then watch the example layout to compare the role of each top-level directory with the locations listed in your asset inventory.

Directory-layout assumptions worth finding

Search your scripts for literal paths such as:

data/raw/
reference/
results/
output/
../
~/Downloads/

Each path reveals an assumption. Record it in plain language.

For example:

Observed path or behaviorHidden assumptionRisk if false
data/raw/*.fastq.gzRaw FASTQs are directly below data/raw/, with no sample subdirectories.A valid nested download layout is silently ignored.
reference/genome.faThe correct genome FASTA always has this exact name.A different assembly or stale reference can be used unintentionally.
results/counts.tsvOne count matrix exists and is current.A rerun may overwrite or reuse an incompatible matrix.
../metadata/sample_sheet.csvThe script runs from a particular subdirectory.The same script fails when launched from the project root or another machine.
~/project/...The project exists at the author’s personal absolute path.The pipeline is not portable.

The Data Carpentry guidance is useful here because it connects human-readable organization with machine-readable structure. Metadata and directories must be designed for the commands that will consume them, not only for visual browsing.

Project Organization and Management for Genomics: All in One View

Read this Data Carpentry guidance to sharpen the difference between conventions that are easy for a human to guess and rules that a computational workflow can use consistently.

In “Structuring data in spreadsheets,” read the structuring rules. Focus on one observation per row, one variable per column, machine-safe column names, and keeping separate pieces of information in separate fields. Then scan the “Sending samples to the facility” example and its solution, especially the list of inconsistent identifiers, capitalization, dates, and numeric formats. Treat these as examples of assumptions that are easy to miss until a script or statistical model depends on them.


Metadata contains the most consequential assumptions

Metadata is where biological meaning enters the pipeline. A pipeline can align reads correctly and still produce an invalid differential-expression comparison if the metadata are incorrectly interpreted.

In the previous lesson, you began sample_metadata.tsv with one row per analysis unit. Now inspect it for the assumptions embedded in that structure.

1. What does one row represent?

Your metadata table may assume that one row is:

  • one biological specimen;
  • one library preparation;
  • one sequencing run;
  • one lane-level FASTQ pair; or
  • one count-matrix column.

For DESeq2, the practical rule is that the metadata used to construct the dataset should have one row per count-matrix column. But that does not mean this row is necessarily a biological specimen. If technical libraries were combined before counting, the row may represent a combined analysis sample. Document that relationship.

2. What does each label mean?

The following labels might look equivalent but are analytically different:

control
Control
CTRL
untreated
vehicle
baseline

Do not assume they represent the same experimental condition. A label can reflect treatment status, collection time, a control substance, or an investigator’s shorthand.

Likewise, batch can mean different things:

  • RNA extraction batch,
  • library-preparation batch,
  • sequencing run,
  • sequencing lane,
  • laboratory operator,
  • sample collection cohort.

If you use a variable in a design formula later, you must know exactly what it measures. A generic batch column with undocumented meaning is not enough.

3. Are variables atomic?

Avoid composite values such as:

treatment_batch2_female
control_RIN7.8
tumor_stage3

These encode several variables in one string, making filtering, checking, and modeling error-prone. Separate them:

condition = treatment
library_batch = batch_2
sex = female
rin = 7.8

This is not merely a spreadsheet preference. It determines whether you can later check balance across groups, identify confounding, or include a scientifically justified covariate in a model.

4. Are missing values meaningful?

Your pipeline may currently treat these as interchangeable:

blank cell
NA
N/A
unknown
-
not_available

They are not interchangeable unless you define them as such. Use a documented missing-value convention. Distinguish, when useful:

  • not collected;
  • not known from the public record;
  • not applicable;
  • awaiting verification.

For a job-ready repository, it is better to state that a sequencing-center field is unavailable than to fill it with a plausible guess.


Reference resources are metadata, too

Your current pipeline probably contains reference-related assumptions even if the reference files are stored outside the repository.

At minimum, identify:

  • organism and strain, when applicable;
  • genome assembly, such as GRCh38;
  • FASTA source and release;
  • GTF or GFF source and release;
  • whether chromosome names include a chr prefix;
  • whether gene IDs retain version suffixes, such as .1;
  • aligner or quantifier index source and creation parameters;
  • whether your count matrix retains Ensembl IDs, symbols, or another identifier type.

A common failure is using a genome FASTA from one provider with an annotation from another, where chromosome names or identifier conventions differ. The pipeline may finish, but reads or genes can be omitted because names no longer match. Record the actual files and versions used, not simply “human genome” or “GRCh38.”

This belongs in your assumption audit because a script that accepts arbitrary genome.fa and annotation.gtf without checking compatibility is assuming compatibility.


Create an assumption audit for your RNA-seq project

Create a working document such as:

docs/assumption_audit.md

Do not try to solve every issue immediately. First make the contracts visible. A compact table is enough:

IDWhere observedAssumptionEvidenceConsequence if falseStatusFollow-up
FN-01FASTQ parserRead 1 files end in _R1.fastq.gz.All current files match.Files may be skipped.verified for current dataValidate before processing.
FN-02Sample ID extractionOne FASTQ pair equals one biological sample.Lane labels are present.Technical runs may be treated as replicates.uncertainCompare with source sample sheet.
DIR-01data/raw/Raw data are immutable and never overwritten.No write command found.Original inputs may be lost.partly verifiedAdd checksum record.
META-01condition columnValues use exactly control and treatment.One value is Control.Samples may split into unintended groups.violatedStandardize and document permitted values.
REF-01Reference pathsFASTA and GTF use compatible chromosome names.Sources not recorded.Gene counting may omit features.unknownCreate reference manifest.

Use four status labels consistently:

  • verified: you have direct evidence the assumption holds for the current project.
  • uncertain: plausible, but not yet checked.
  • violated: evidence shows it is false or inconsistent.
  • intentional: a deliberate project rule that should be documented and validated later.

A focused audit workflow

Work through the project in this order:

  1. Start with the sample sheet and count matrix.
    Compare count-matrix column names with sample_metadata.tsv. Determine precisely what one analysis sample represents.

  2. Inspect a representative set of filenames.
    Include at least one file from each condition, each lane or run, and any unusual naming pattern. Note every token your Bash script extracts or discards.

  3. Read your scripts as if you were a new collaborator.
    Search for hard-coded paths, wildcard patterns, suffix stripping, implicit default parameters, and sample-name transformations.

  4. Inspect the directory tree.
    For every major folder, write one sentence defining what belongs there, whether contents are immutable or regenerable, and which script reads or writes there.

  5. Inspect metadata values as controlled vocabulary.
    Look for inconsistent capitalization, spaces, date formats, missing-value markers, composite fields, and duplicate IDs.

  6. Trace reference provenance.
    Find the FASTA, GTF, index, or configuration currently used. If the version is unknown, mark it unknown rather than guessing.

A useful outcome is not “all assumptions are fixed.” A useful outcome is a list of explicit, prioritized risks. For example, an undocumented lane-merging rule is more urgent than whether a figure filename uses hyphens or underscores, because it can change the number of biological replicates in the analysis.


What to preserve in the portfolio repository

Your audit should produce evidence that another analyst can inspect:

docs/assumption_audit.md
metadata/sample_metadata.tsv
metadata/asset_inventory.tsv
metadata/reference_manifest.tsv
docs/metadata_dictionary.md

At this stage, these files can be short. Their value is that they separate:

  • what is known from what is inferred;
  • intentional conventions from accidental habits;
  • biological metadata from filename shorthand;
  • raw input identity from derived-output identity;
  • a current working run from a reproducible project specification.

Avoid “fixing” an inconsistency by silently renaming files or editing metadata without recording the decision. If you change Control to control, document the permitted vocabulary. If you merge lane-level FASTQs, document the source runs and the resulting analysis sample. If you replace a reference annotation, record the old and new versions.


Key takeaways

A working RNA-seq pipeline contains many contracts, whether or not they are written down.

  • Filenames may assume a read-pair convention, one lane per sample, a particular suffix, or a recoverable sample ID.
  • Directory layouts may assume a working directory, a fixed location for inputs, or a distinction between immutable and regenerable files.
  • Metadata may assume a row represents one biological sample, that labels have controlled meanings, and that missing values are consistently encoded.
  • Reference resources may assume compatible genome assemblies, annotations, chromosome names, and gene identifiers.
  • The practical response is an assumption audit that records each assumption, its evidence, its impact if false, and its status.

Next, you will turn the most important findings into measurable acceptance criteria for a successful pipeline run and a trustworthy differential-expression result.

Can't find a good explanation? Sign up and we'll make it for you

Sign up