Results & Outputs
A Nextflow workflow writes files. SeqDesk’s job is to turn a subset of those files into database records that the rest of the application can use: an assembly you can submit to ENA, a checksum a submission check can verify, a report a researcher can open. That translation is called output resolution, and it is entirely driven by the package’s declared outputs.
How resolution works
When a run reaches completion, SeqDesk scans the run folder’s output/
directory and matches files against each declared output’s discovery pattern —
a glob, plus a rule for associating a file with a sample (by filename, or by
parent directory). Each matched file is then routed by its destination:
| Destination | What SeqDesk creates | Notes |
|---|---|---|
sample_assemblies | an Assembly row linked to the sample | unique per (run, sample, file) |
sample_bins | a Bin row, with completeness/contamination if a parser supplies them | unique per (run, sample, file) |
sample_reads | a write onto the canonical Read record | see Read writeback |
sample_qc, sample_metadata, sample_annotations | a sample-scoped PipelineArtifact | |
study_report | a PipelineArtifact ranked as the study’s primary report | |
order_report, order_files | a PipelineArtifact scoped to the sequencing order | |
run_artifact | a PipelineArtifact scoped to the run | logs, summary tables, data files |
download_only | nothing | the file stays on disk, browsable but unrecorded |
Three properties follow from this and explain most surprises:
- Resolution is idempotent. Artifacts are unique per
(run, path), assemblies and bins per(run, sample, file). Re-running resolution — which happens whenever a weblog completion and the monitor race each other — skips what already exists instead of duplicating it. - A pattern that matches nothing is not an error. The run still completes; the artifact is simply absent. If a completed run shows no results, the first thing to check is whether the produced filenames match the package’s declared patterns.
- The workflow never writes to the database. It writes files. SeqDesk reads them and performs every write itself, after validating the declared contract.
A summary of each pass is stored on the run as JSON: assembliesCreated,
binsCreated, artifactsCreated, pendingWritebacks, plus errors and
warnings when there were any. Errors here mean ingestion problems, not
pipeline failures — a run can be completed and still report output errors, and
the Pipeline Runs table flags that.
Where files live
Nothing is moved by default. Discovered outputs are recorded with their absolute path inside the run folder:
/data/pipeline_runs/MAG-20260415-003/output/…The two exceptions are the writes that have to become permanent data:
-
Promoted read candidates are copied into the data base path under a deterministic layout, so deleting the run folder cannot orphan an active read:
<dataBasePath>/_pipeline/orders/<orderId>/<pipelineId>/<runNumber>/<sampleCode>/<outputId>/R1-<filename> -
Assemblies and bins keep their run-folder paths but are referenced from
Assembly.assemblyFile/Bin.binFile, which is why deleting a run also deletes those rows.
Artifacts
A PipelineArtifact records one produced file: its path, size, the manifest
outputId it satisfied, the step that produced it, the sample it belongs to
(when sample-scoped), and any parsed metadata as JSON.
The stored type is one of three values, derived from how the package
classified the file: report, qc, or data. Artifacts are the generic
container — anything that is not an assembly, a bin, or a read write ends up
here.
The results list on a run
The run row in Pipeline Runs, and the run detail page, show a curated list rather than every file:
- Sample-scoped artifacts are excluded from the top-level list and counted separately, so a 200-sample run does not bury its one summary report.
- The list is capped at 12 files; anything beyond that is reported as an omitted count and remains reachable through the file browser.
- Files are ranked, not alphabetised. An output whose package marks it as the
primary preview ranks highest, followed by
study_report/order_reportdestinations, then reports, then HTML, then PDF, then tabular formats. Logs are pushed down. - Nextflow’s own
report.htmlis added as Nextflow report if it exists, and is deliberately ranked below real results. - A file is previewable inline only if its extension is one of
.html,.htm,.pdf,.txt,.tsv,.csv,.log,.jsonand it lives inside the run folder.
The Pipeline Output tab is the uncurated view: a browser over everything
under output/, walking up to 10 directory levels and 1000 files, with dotfiles
skipped.
Assemblies
An Assembly is a set of contigs for one sample.
| Field | Meaning |
|---|---|
assemblyName | display name, usually derived from the sample |
assemblyFile | path to the contig FASTA |
assemblyAccession | ENA accession once submitted (ERZ…) |
sampleId | the sample it belongs to |
createdByPipelineRunId | the run that produced it |
The MAG package discovers assemblies with the pattern
Assembly/*/*.contigs.fa.gz, matching the sample by filename — the wildcard
directory means MEGAHIT and SPAdes output both resolve, so one sample can end up
with several assemblies.
Preferred assembly
Because a sample can have more than one assembly, one must be chosen for
downstream use — in practice, for ENA submission. Sample.preferredAssemblyId
records an explicit choice; when it is unset, SeqDesk falls back to the newest
assembly, ordered by the creating run’s timestamp.
That produces four selection states, shown as a badge in the Selection column:
| Badge | Meaning |
|---|---|
| Marked Final | an admin explicitly set preferredAssemblyId and it resolves |
| Automatic | no explicit choice; the newest available assembly is used |
| Missing Preferred | an explicit choice exists but that assembly is gone — shown with Preferred assembly is missing |
| Unavailable | the sample has no assembly with a file |
Missing Preferred is not cosmetic. Submission validation resolves the preferred assembly strictly, so a dangling choice blocks the run rather than silently falling back:
Sample S-… has an invalid preferred assembly selection (update it in Study Analysis)Genome bins
A Bin is one genome extracted from a metagenomic assembly.
| Field | Meaning |
|---|---|
binName | bin identifier |
binFile | path to the bin FASTA |
binAccession | ENA accession once submitted |
completeness | CheckM completeness, 0–100 |
contamination | CheckM contamination, 0–100 |
MAG discovers bins at GenomeBinning/DASTool/bins/**/*.fa, matching the sample
by parent directory, and falls back to
GenomeBinning/{MetaBAT2,MaxBin2}/**/*.fa when DAS Tool produced nothing. DAS
Tool bins are refined — they combine and de-replicate the output of the
individual binners — which is why they are preferred.
Completeness and contamination are not read from the FASTA. They come from a
declarative parser that reads GenomeBinning/QC/checkm_summary.tsv and joins on
the bin name. If that file is missing, bins are still created; their quality
columns are simply empty.
The conventional interpretation of those numbers (MIMAG-style):
| Category | Completeness | Contamination |
|---|---|---|
| High quality | ≥ 90% | < 5% |
| Medium quality | ≥ 50% | < 10% |
| Low quality | < 50% | any |
SeqDesk stores the values and displays them; it does not enforce a threshold or filter bins by quality.
Taxonomy is handled the same way: a parser reads
Taxonomy/GTDB-Tk/*.summary.tsv, joins on bin name, and attaches the
classification as sample metadata.
Read writeback and candidate review
Order pipelines write to the canonical Read record. Which of the three
behaviours applies is decided by the package’s declared result kind — see
Pipeline Scopes
for the full mapping.
| Result kind | Behaviour |
|---|---|
sample_read_metadata | merges scalars — checksums, read counts, average quality, report paths — onto the active read |
sample_read_replace | creates or supersedes the canonical read files |
sample_read_candidate | stores the files as run artifacts and holds them for review |
Reviewing candidates
Read Cleaning is the pipeline that uses the review path. Its cleaned FASTQ files are staged, not applied, and the run’s page shows Review pending read outputs with one row per sample: the candidate files, the sample’s current active reads, and a Candidate or Promoted badge. Selecting rows and pressing Set as active reads promotes them, behind an explicit confirmation checkbox.
Promotion is deliberate about what it does to existing data:
- The candidate file is copied out of the run folder into the data base path
(the
_pipeline/orders/…layout above). Its source path is checked to be inside the run folder first — a candidate pointing anywhere else is rejected. - MD5 and read count are computed for the copy.
- A new
Readrow is created withdataClassSource: "pipeline"and a classification note naming the run. - Every currently-active read on that sample is deactivated and linked to
the new read via
supersededByReadId, then the new read is activated.
“Preserved” means kept, not kept active. A sample may have at most one active read, so promoting a cleaned read deactivates the raw read too. The raw row is never deleted and remains linked for provenance — but after promotion, delivery and downstream order pipelines use the cleaned read.
Guards worth knowing: promotion requires a completed, order-scoped run
(Only completed pipeline runs can be promoted, Pending read promotion requires an order-scoped run), a configured data base path, and at least one
un-promoted candidate (No pending read candidates selected for promotion). A
double submit cannot create two active reads — the transaction re-checks for an
existing read promoted from the same run and sample.
API
| Method | Endpoint | Purpose |
|---|---|---|
GET | /api/pipelines/runs/[id]/pending-writebacks | list candidates, their status, and the target read data class |
POST | /api/pipelines/runs/[id]/pending-writebacks | promote selected candidates (sampleIds in the body; omit to promote all) |
GET/POST | /api/pipelines/runs/[id]/cleaned-reads | the Read-Cleaning-specific alias for the same flow |
All four require FACILITY_ADMIN, and promotion is disabled in the public demo.
Publishing a run to the researcher
By default, a pipeline run is invisible to everyone except facility admins —
including the researcher who owns the study or the sequencing order. Read access
requires both ownership and publication; without publication the run’s API
routes answer 403 Forbidden.
Publication is the Use as final action in a run’s row menu. It records a
PipelineResultSelection keyed by (pipelineId, target), so one run per
pipeline per study or order is the final one. Selecting a different run moves
the marker; Clear final removes it and makes the run private again.
Constraints:
- FACILITY_ADMIN only, and disabled in the public demo.
- Only completed runs qualify:
Only completed pipeline runs can be selected as final. - The run must have a target:
Pipeline run does not have a study or order target.
The selected run carries a Final badge in the Pipeline Runs table.
This is the deliberate answer to “why can’t my user see the report?”. Finishing a run is not the same as releasing it. Nothing reaches a researcher until an admin decides which run is the answer.
Assemblies Viewer
The Assemblies page (/assemblies) is the cross-study view of every sample
that has an assembly and belongs to a study.
| Column | Contents |
|---|---|
| Study | study title, with the sequencing order number below |
| Sample | sample identifier |
| Final Assembly | assembly name, file name, and either Run <runNumber> or Manual upload |
| Selection | the badge described under Preferred assembly |
| Available | how many assemblies exist for that sample |
| Action | download link, or Unavailable |
Visibility rules:
- Facility admins see every sample with an assembly.
- Researchers see only samples in their own studies, in orders whose status
is COMPLETED — and only when the
allowUserAssemblyDownloadsetting is on. With it off, the page answersAssembly downloads are disabled by the facility administrator. - The page is disabled entirely in the public demo.
Deleting a run
Deleting a run is a FACILITY_ADMIN-only action available from the run’s row menu (Delete run) or in bulk via Select → Delete. It is irreversible, and it removes more than the run row.
What happens, in order:
- A
runningrun is refused:Cannot delete a running run. Cancel it first. - A
pendingorqueuedrun that already has a scheduler job is cancelled first, so the job is not orphaned against a deleted folder. - For a terminal run, output cleanup runs — but only for packages that
declare a
sample_readsdestination. For those, the read files this run materialised are deleted, and read rows or metadata fields it wrote are cleaned up. Cleanup is scoped to the run’s own samples, and a metadata-only pipeline clears the fields it wrote rather than deleting the read. AssemblyandBinrows created by the run are deleted.- Steps, events and artifacts are deleted (they also cascade).
- The run row is deleted.
- The run folder is removed from disk, best-effort.
Deleting a MAG run therefore deletes its assemblies and bins — and any ENA accession recorded on them. Deleting a Simulate Reads run deletes the FASTQ files it generated. Deleting a FastQC run clears the metrics it wrote, but leaves the reads alone, because FastQC never produced them.
Re-resolving outputs without re-running
If a run completed but its outputs were not picked up — a late file, a fixed discovery pattern, a transient storage error — an admin can re-run resolution alone:
POST /api/pipelines/runs/{id}/resolve-outputsIt accepts only completed or failed runs
(Can only resolve outputs for completed or failed runs), needs a run folder
(Run folder not set) and samples (No samples found for this run). Because
resolution is idempotent, running it repeatedly is safe.
Where to find results
| Surface | Shows |
|---|---|
| Analysis on a study or order | one card per pipeline with its run history |
| Per-pipeline page → Pipeline Runs | every run, its status, curated result links, and the Final badge |
| Run detail → Status | detected assemblies and bins, plus live logs |
| Run detail → Pipeline Output | the full file browser over output/ |
Assemblies (/assemblies) | every assembly across studies |
| Sample detail | that sample’s assemblies and bins |
Related pages
- Monitoring a Run — how a run gets to the point where outputs are ingested.
- Study vs Sequencing Order Pipelines — which writes each scope may make.
- Available Pipelines — the declared outputs of every shipped package.
- Adding Custom Pipelines — writing discovery patterns and result contracts.
- ENA Submission — what happens to assemblies and bins afterwards.