grave is a Nextflow workflow for aligning, genotyping, and variant calling ancient or modern short-reads against a pangenome graph. A simplified summary of workflow steps is found here. A Wiki with further detail is available here.
Typically, the inputs to grave are a pangenome graph in .gbz format and a .csv samplesheet specifying FASTQ files (paired-end or merged/single-end).
Note
To compare the outcomes of graph versus linear reference-based alignment methods, grave can also be run in linear mode, taking a FASTA assembly instead of a graph.
Workflow outputs are described here.
More information on genotyping and variant calling is found here.
It is recommended to construct the graph with Minigraph-Cactus. Before doing so, read this section.
- Install Pixi:
curl -fsSL https://pixi.sh/install.sh | sh - Clone the Workflow repository:
git clone https://github.com/NBISweden/grave.git - Run
cd grave && pixi install
Note
The pixi project contains two environments:
default: installed with pixi install. This lacks apptainer (e.g. for systems with an existing Apptainer installation).
apptainer: installed with pixi install -e apptainer. This provides an Apptainer installation.
- At minimum,
gravecan be run withNextflowand eitherApptainer,Singularity, orDockerinstalled in$PATH - However, it is recommended to run it via
pixi pixiis a drop-in replacement forconda, andgraveuses it to install its basic dependencies.pixienvironments have an editable manifest file, thepixi.toml- Solved environments also have a
pixi.lockfile, which fixes the versions of all dependencies including transitive ones. The lockfile in this repository represents an environment that has been tested on Linux systems. - Installed
pixienvironments are found in the hidden folder.pixi/envs pixiwill automatically install an environment it lacks, if implied by another command (e.g.,pixi run -e apptainer ...will install theapptainerenvironment if it is not found).- You can run commands in a
pixienvironment by prefixing them withpixi run(or in a specific environment withpixi run -e <environment>). - Alternatively you can enter a software environment with
pixi shell(or a specific environment withpixi shell -e <environment>), similar toconda activate <environment> - To delete an environment:
rm -rf .pixi/envs/<environment_name>
-
To run a test with provided data:
pixi run test-apptainer -
Or using Docker:
pixi run test-docker
Tip
All pixi run commands use the default environment. To specify the apptainer environment:
pixi run -e apptainer test-apptainer
-
graveaccepts three types of reference:filtered_graph,unfiltered_graph, orlinear(i.e., FASTA assembly). -
Graphs should be in
.gbzformat, such as those produced by Minigraph-Cactus, a workflow within the Cactus package. Graph indexes are not required -gravewill create the necessary indexes for ancient and/or modern input samples. -
When using
Minigraph-Cactusfor graph construction, keep input assembly contig headers simple (see the official guidance here), and without special characters.
-
A filtered graph is one with depth filtering applied, i.e., nodes not represented in at least
depthhaplotypes are removed from the graph. Typically this is set to around 10% of the number of haplotypes (i.e.,40 pseudohaploid assembliesor20 phased assemblies->depth 4). -
The
MiniGraph-Cactusoption--giraffegenerates a graph filtered to depth 2. Depth is adjusted with the--filterparameter, e.g.:--giraffe --filter 10 -
The resulting graph can be provided to
gravewith--reference graph.d10.gbz --reference_type filtered_graph -
The cost of depth filtering is that rarer variants are lost from the graph. This should be considered when users are building a graph from relatively divergent assemblies, or when some constituent species have fewer haplotypes than others (e.g., an outgroup has a single haplotype, while the ingroup has many).
Important
- For samples with high coverage (e.g., 20X) and high purity in terms of endogenous content, the current best practice is to use an unfiltered graph. With this approach, K-mers from the reads are used to sample representative haplotypes from the graph, and reads are aligned to the subset.
- For samples with degraded, short, and low coverage endogenous content, plus high levels of contamination, filtered graphs are likely to be preferable, as we expect the K-mer-based subsampling to underperform.
- Running in unfiltered graph mode utilises K-mer profiling of the reads to sample representative haplotypes from the graph for mapping, read more here and here.
Important
See the above section, users should consider (or test) whether an unfiltered graph is appropriate for their samples.
-
To build an unfiltered graph, run
MiniGraph-Cactuswith option:--haplo(--giraffeis not required). -
The clipped, unfiltered graph can be provided to
gravewith--reference graph.gbz --reference_type unfiltered_graph
Complete a samplesheet.csv file, detailing file system paths to your reads. The layout is shown below:
Tip
The table below is an example. The file provided to grave must be in .csv format
| sample_id | library_id | repeat_number | sample_type | merged | fastq1 | fastq2 |
|---|---|---|---|---|---|---|
| ancientHuman1 | 1 | 1 | ancient | false | /path/to/read1.fq.gz | /path/to/read2.fq.gz |
| ancientHuman1 | 1 | 2 | ancient | false | /path/to/read1.fq.gz | /path/to/read2.fq.gz |
| ancientHuman1 | 2 | 1 | ancient | false | /path/to/read1.fq.gz | /path/to/read2.fq.gz |
| modernHuman7 | 1 | 1 | modern | false | /path/to/read1.fq.gz | /path/to/read2.fq.gz |
| mergedInput | 1 | 1 | ancient | true | /path/to/merged.fq.gz |
-
sample_id: unique sample identifier -
library_id: unique library identifier -
repeat_number: repeat number of the library -
sample_type: sample is ancient or modern - Note: this affects how the sample will be processed -
merged: whether the reads have already been merged (e.g., some ancient samples) -
fastq1: relative or absolute path to the first FASTQ -
fastq2: relative or absolute path to the second FASTQ
-
Custom parameters should be set by editing a
params.ymlfile, and providing it on the command line when you execute the workflow (-params-file params.yml). -
An important parameter is
--steps, a string specifying which pipeline subworkflows to run, e.g., (--steps 'index,preprocess'). Each requested step has further dependencies which the user will be prompted to provide. The default is to run all steps for a graph reference input. -
Use
pixi run helpto see available parameters and their descriptions.
Important
The graph aligner vg giraffe uses a seed, cluster, chain, and extend strategy, with two important parameters: K-mer length (k) and window length (w). During graph indexing, minimisers are calculated from the graph, by sliding across length w and taking the sequence (minimiser) of length k with the smallest hash value. The seeding stage of alignment involves computing exact matches between these minimisers and reads. Nearby seeds are clustered and chained together via ungapped alignment, with high-scoring chains serving as the starting point for extension.
Users should keep in mind that reads shorter than k+w-1 cannot be aligned, as they are too short for minimiser computation. Furthermore, with very short reads (~30 bp) users may notice fewer high quality alignments (MAPQ 30+) - this is expected if there are many comparably scoring chains entering extension, thus many potential secondary alignments for a read.
To address these issues, grave uses different k and w defaults for modern and ancient reads:
Modern samples are run with giraffe defaults, emphasising higher specificity (k = 29, w = 11).
For aDNA reads, a reduced k and w results in a low-specificity, high-density index - relying on chaining to discriminate good matches from spurious ones. The grave aDNA defaults (k = 15, w = 3) have acceptable performance at 30 bp and good performance at 40+ bp, though a MAPQ filter of 30 is recommended to filter out alignments from contaminants. Users may find that adjusting these parameters for their particular dataset can improve performance.
Suggested further reading: Rubin et al., 2025, NAR Genomics and Bioinformatics. As the authors note, there is no single best setting for k and w in the aDNA context, as it depends on several factors related to the graph and reads.
Comparison of alignment parameters
| Alignment tool | |--- | Accurate | reads per | million | ---| | |--- | Inaccurate | reads per | million | ---| |
|---|---|---|---|---|---|---|---|---|---|---|
| Read length* | 30 | 40 | 50 | 60 | 70 | 30 | 40 | 50 | 60 | 70 |
grave: k-13/w-3 |
516,840 | 660,570 | 749,380 | 797,680 | 831,130 | 2,980 | 4,430 | 4,270 | 4,160 | 5,290 |
grave: k-15/w-3 |
459,420 | 654,470 | 754,550 | 803,160 | 837,050 | 2,790 | 4,420 | 4,910 | 3,980 | 4,840 |
grave: k-15/w-5 |
354,410 | 627,050 | 744,380 | 797,360 | 831,850 | 3,330 | 4,610 | 4,970 | 4,150 | 5,040 |
grave: k-19/w-3 |
396,080 | 603,760 | 740,410 | 805,890 | 841,830 | 6,910 | 4,600 | 5,150 | 4,500 | 4,910 |
grave: k-19/w-5 |
410,240 | 578,510 | 724,250 | 797,790 | 836,140 | 8,750 | 5,350 | 5,250 | 4,830 | 5,000 |
bwa aln: -l 16500 -n 0.01 -o 2** |
558,200 | 560,550 | 654,450 | 684,310 | 740,200 | 6,910 | 2,830 | 3,470 | 3,160 | 3,950 |
*~100k read pairs were generated per fragment length with NGSNGS from a related assembly not present in the benchmarking graph (sheep). Unmapped reads were removed and MAPQ 30 was applied.
**The bwa linear reference was the same used as the graph backbone (GCF_016772045.2).
Timings refer to the entire alignment modules, not just the aligners themselves.
Note that within grave, bwa defaults to use 6 cpus, while vg giraffe uses 64.
-
Minigraph-Cactusrequires at least one reference sample, usually the most contiguous reference assembly, e.g.:cactus-pangenome --reference GRCh38 -
If your graph has a single reference sample, you can skip this section.
-
Paths through the reference sample are called reference paths. Unless configured otherwise,
gravewill assume a single reference sample, and use rational defaults that assume the same, for examplesurjectwill transform GAM alignments to linear BAM relative to all reference paths in the graph. If there is more than one reference sample in the graph, this will cause undesirable outputs in certain steps, and errors in others. -
Therefore, if your graph was built with multiple reference samples, e.g.:
cactus-pangenome --reference GRCh38 chimp gorilla, it is required to rungravewith--multiple_references, and to provide one or more.pathsfiles. -
Each
.pathsfile contains a list of the reference paths in one reference sample, with one path name per line. -
The name of the
.pathsfile matters: the prefix must match a reference sample name provided in theseqFileofMinigraph-Cactus, and the suffix must be.paths, e.g.:GRCh38.paths,chimp.paths, andgorilla.paths
Tip
vg is packaged in the pixi environment, to see the reference samples in your graph run: pixi run vg paths --reference-paths --metadata -x myGraph.gbz | cut -f3 | tail -n+2 | sort | uniq
For a list of all reference path names from, for example GRCh38, run: pixi run vg paths --reference-paths --metadata -x myGraph.gbz | tail -n+2 | awk '$3 == "GRCh38"' | cut -f1 > GRCh38.paths
- For each
.pathsfile provided,gravewill run pipeline steps relative to that sample separately from the others, e.g.,surjectwill produce a separate.bamfile per reference sample, such that surjectingunknownSimian.1.gamtochimp.pathsandgorilla.pathswill produce:
unknownSimian.1.chimp.bam
unknownSimian.1.gorilla.bam
Example of how to run a local test (not recommended for production runs)
pixi run -e apptainer nextflow main.nf -profile apptainer,test -params-file params.yml
Running at scale (e.g., on SLURM cluster)
-
It is usually good practice to run
gravevia atmuxorscreensession rather than directly on the login node. An editable shell script that will do this for you is available inbin/slurm_submission.sh -
Institutional profiles are available via
nf-corefor many major HPC centres, see here. The example command below configuresgravefor the Dardel cluster in Stockholm, Sweden. -
When running on a cluster using the
slurmjob scheduler, ensure you provide a project allocation number using the--projectparameter. This can be on the command line or via theparams.ymlfile.
pixi run nextflow main.nf -profile pdc_kth -params-file params.yml --project example-allocation-12345
Tip
By default results are stored in the results directory. Exact outputs depend on the settings used
| Output directory | Description |
|---|---|
| 01_pipeline_info | Package versions, run parameters, and Nextflow trace reports (if set) |
| 02_reference | Reference statistics and reference FASTA files extracted from graphs with Pan-SN headers + index |
| 03_read_qc | Read QC reports |
| 04_mapped_reads | Mapped reads (library level GAM/BAM, surjected/merged/deduplicated BAM, alignment statistics, failed samples) |
| 05_post_mortem_damage | Post-mortem damage profiles (only for samples with the ancient metadata tag) |
| 06_genotyping | Genotyping outputs directly from the graph, and per sample |
| 07_variant_calling | Variant calling outputs per sample |
Tip
The workflow also computes graph indexes and snarls, stored in folders alongside the input graph (detected on repeat runs)
Tip
grave outputs BAM files surjected to reference assemblies in the graph, therefore users can use these in custom downstream tools
vg deconstructproduces a VCF file with a line for every snarl (bubble) in the graph. Allele information (reference vs alt) is taken from paths in the graph, read more here.
vg callgenotypes graph variants present in each mapped sample (i.e., no novel variant calling), read more here.- It takes GAM files as input, and therefore users should note that no deduplication is done prior to genotyping, see here.
Freebayesis integrated ingrave, read more here.
DeepVariantis integrated ingrave(currently recommended for human input data only), read more here.
-
gravecan be run in linear reference mode, mapping reads against a single FASTA reference instead of a graph. -
Ancient DNA alignment will be run with
BWA aln(-l 16500 -n 0.01 -o 2) and modern DNA withBWA MEM(default settings). -
To configure linear mode, set the parameter
reference_typetolinear, and provide a FASTA reference with thereferenceparameter.

