TITLE: A standard pipeline for processing short-read sequencing data from Littorina snails
AUTHORS: James Reeve, Amin Ghane, Pierre Barry, Alfonso Balmori-de la Puente, Roger K. Butlin, Le Qin Choo, Alan Le Moan, Diego Garica Castillo, Ana-Maria Peris Tamayo, Sarah Kingston, Erica Leder, Sean Stankowski

[DESCRIPTION]
This protocol explains the default pipeline we recommend for analysing short-read data for Littorina marine snails. The pipeline was designed based on our experience processing WGS data, and careful consideration of the available tools. We are presenting this protocol as a suggestion of how Littorina sequencing data can be processed, and as a template for building more specific pipelines. Our hope is that through writing this protocol we can have more consistency among projects, leading to greater transparency for collaborators and providing a template which could be used to build pipelines for other organisms.

[GUIDELINES]
This protocol was created as a guide for new users. We strongly recommend exploring your data and reading the manuals for the software we present, before designing your own sequence data pipeline.

[STEPS]
SECTION: Overview
1. Processing of short read sequencing data can be broken down into four major steps (Fig. 1): 
      1) read quality inspection and trimming
      2) read mapping
      3) variant calling 
      4) variant filtering
There are numerous sub-steps in between, which together have a plethora of different adjustments one could make. Without a reference, two users could create vastly different pipelines for the same data. Below, we outline our recommended pipeline steps, briefly describing the process, showing example code, and explaining the different options available. 

 Speeding things up [optional]:
	Our recommendations are not the most optimised pipeline. We purposely go into detail for each step to explain the process. Once you are familiar with this pipeline, you can pipe commands together to skip generating intermediate files. Large files (e.g. fastq, BAM and VCF) can also be compressed to reduce storage space, which will speed up the analysis.

 
 







SECTION: Read quality inspection and trimming
2. Short-read sequencers output raw data in fastq format. This contains nucleotides along with a Phred-likelihood quality score for each base (the probability that the called base is wrong). Bases at the end of reads often have lower quality than those at the start. Trimming these poor quality bases is recommended using a tool like fastp. (Del Fabbro 2013, Chen et al. 2018). Base quality is not the only metric that can be used to evaluate reads; other important statistics include read length, GC content, duplications and adaptor content (HBCtraining, n.d.). We recommend using fastqc to generate summary reports of read quality. For datasets of many individuals, these reports can be merged with MultiQC.


SECTION: Read mapping
5. Once we have good quality reads, we next map them onto the Littorina saxatilis reference genome (De Jode et al., in review). At the simplest level, read mapping is just aligning DNA sequences. The complexity comes in when trying to optimise this process for next generation sequencing data (Trapnell and Salzberg 2010). We recommend using the Burrows-Wheeler Aligner (BWA). Other read callers can do a similar job, but BWA has the highest accuracy in benchmarking papers (Musich et al. 2021, Zanti et al. 2021, Schilbert et al. 2020). BWA takes two fastq files as input per sample, the forward and reverse reads. If sequencing data are paired-end, then BWA outputs a single SAM file. This output adds additional information to the fastq which shows where each read is placed on the reference genome and if there are any mismatches. SAM files tend to be massive, so as a final step we compress them to BAM format.
SECTION: Variant calling
9. Variant calling sifts through multiple BAM files to identify genomic positions that vary among individuals. These variants can include indels, SNPs, SNVs, or repeated elements. The most common variants used in evolutionary research are SNPs. SNP calling identifies positions where two (or more) versions of a nucleotide are present in a population. Each individual is also assigned a genotype, often scored as ‘0/0’ if  homozygous for the reference allele (i.e., the individual carries two alleles that match the allele in the reference genome), ‘1/1’ if homozygous for the alternative allele, and ‘0/1’ if heterozygous. Individuals with no called genotype at this position are scored as ‘./.’.

 Genotypes can be called with a range of different models (one of the key distinctions among different calling software packages) that give each individual three probability scores (one for each possible genotype) at each biallelic site. In addition, other metrics, such as depth of coverage (i.e. how many reads are used), mapping quality and strand biases, are provided. All of this information is stored in a variant call format (VCF) file. 

We recommend calling variants using the program bcftools. It performed quicker and as accurately (evaluated with precision and recall) as a more popular caller (GATK; https://gatk.broadinstitute.org/hc/en-us), when tested on sequence data from a set of Littorina parent-offspring trios. There are two steps to calling with bcftools; first, sequences from each BAM file are concatenated together into an mpileup file. 
SECTION: Variant filtering
10. After calling, variants must be filtered to remove possible poorly sequenced, low quality sites and undesired types of variant (e.g. indels). This step will vary most between studies, as filtering thresholds depend heavily on the type of data, sequencing approach and end results of the analysis. The recommendations we give below are intended to provide some advice for new users, as a benchmark for some of the most common filters. Depending on the downstream analysis and other factors like sample number and sequencing depth, some criteria might need tweaking. For instance, for low coverage data a lot of information may be lost with the filters proposed here. On the other hand, for very precise analysis, even more stringent filters are required. Ultimately, judgement is left up to the user; we recommend extracting variant quality scores (e.g. DP, SP, MQ, or QUAL) from the VCF and plotting their distributions before choosing filtering thresholds. 

Main steps in filtering:
It is best to think about filtering as three steps. 
Hard filtering: the removal of entire variants, purging their record from the VCF file
Soft filtering: the masking of individual genotypes from the file by setting these as missing data
Filter by the proportion of missing data: removing entire sites where fewer than x% of individuals have a genotype

A note on applying filters:
It is tempting to apply filters in a single command which removes sites or masks genotypes based on multiple criteria simultaneously. Although this may seem more efficient, it is difficult to check that filters are applied as expected. It is much easier to understand the effect of each filter if they are run separately, or in small sets. The number of sites left after each filter (see code below) should be recorded to keep track of data loss over the entire filtering process . Be sure not to overwrite your original file so you can always go back and filter the dataset based on a different set of criteria if needed.

 

SECTION: Read quality inspection and trimming
3. 1.1) Read quality:
Before trimming and mapping, our reads are evaluated with fastqc per individual and MultiQC for the whole dataset. We run fastqc with default settings, apart from -t which specifies the number of threads (-t will depend on your computer specifications). The resulting quality reports are composed of several sections (e.g. read length, nucleotide content, adaptors, duplication). Detailed example reports and a tutorial video are on the fastqc website. We recommend looking at these before deciding how to trim reads.
 

SECTION: Read quality inspection and trimming
4. 1.2) Read trimming:
We recommend the program fastp for trimming adaptors and removing low quality ends. This program can identify adaptor sequences (assuming standard adaptors were used by the sequencing centre), and other known errors like polyG tails, and automatically trim them from the data.  There are also options to specify adaptor sequences manually and the number of base pairs to clip, if the default settings do not work with the data. fastp also generates a quality report which can be compared with the fastqc reports to see if the trimming is successful.

For paired-end sequencing (Illumina, 2023) you must specify both a forward (-i) and reverse (-I) read files. By default fastp overwrites existing files, we set -o and -O to specify the output. Optional filtering steps we use are -g to trim polyG tails, -c to perform base correction in overlapping paired data, and -y as a complexity filter that removes reads with < 30% complexity (shifts between neighbouring base pairs; basei ≠ basei+1). Finally, --html, --json, and --report_title are set to specify where the output reports are placed.

 
It is a good idea to inspect the reports at this point to determine if read trimming has improved the quality (see fastqc tutorials). If so, move onto read mapping. If not, the fastp options need tweaking until the reads are ready to map.

SECTION: Read mapping
6. 2.1) Index reference genome:
Before running BWA we need to index the reference genome. This helps the algorithm to find shorter sequences throughout the genome, speeding up the whole process (Trapnell and Salzberg 2010). We index the reference genome with the simple one-liner below. This only has to be done once, but remember to keep the index files in the same directory as the reference genome.

 

SECTION: Read mapping
7. 2.2) Mapping reads with BWA:
Reads are mapped to the reference genome using BWA. We use the maximal exact matches (mem) algorithm. Three input files are required: the reference genome, the forward reads fastq and the reverse reads fastq. We optionally set -M to mark shorter splits as secondary alignments (i.e. other parts of the genome with lower quality mapping), -R to specify the read group information (flags that indicate how a read was sequenced and the sample it came from), and -t to set the number of threads to run in parallel. Lastly, the standard output is piped into samtools to write the file in the compressed BAM format.

 

SECTION: Read mapping
8. 2.3) Post mapping read data sorting:
After mapping reads, some additional intermediate steps are needed before we can start variant calling. These steps vary depending on the type of analysis conducted and which software are used. For this default pipeline, we follow the guidelines from the samtools website (http://www.htslib.org/algorithms/duplicate.html). Our intermediate steps are i) reordering reads in the BAM, ii) identifying possible duplicated reads, and iii) creating a summary report. 

SECTION: Read mapping
8.1. 2.3.1) Sort BAM:
Sorting steps are all conducted using samtools. Reads are sorted in two ways, first alphabetically by read name using the -n option, then by genome position with the default sort command. In between these sorting steps, we run the fixmate to fill in missing details among paired reads, with the -m option adding a mate-score tag to the BAM. While this does not seem very important, this step is necessary when we identify duplicates. Each of these samtools commands is piped into a single line of code, to avoid creating a massive number of intermediate files.

 
The samtools -@ option sets the number of threads to run, and the - are placeholders for the input and output files. These placeholders are necessary to pipe different samtools commands together.

SECTION: Read mapping
8.2. 2.3.2) Mark duplicates:
Duplicated reads are identified in the sorted BAM with samtools markdup. PCR duplicates can occur during the amplification steps of library preparation. Another type of duplication, optical duplication, originates from technical artefacts in the clustering on the Illumina flowcell and these are not identified by default. samtools markdup uses coordinate and tile information from the read name to mark optical duplicates, using the -d option to set the distance among coordinates. Both types of duplicates can be removed with the -r option, but this is often not necessary as reads marked as duplicates are not considered by most variant callers.

 

SECTION: Read mapping
8.3. 2.3.3) Index and generate flagstat report:
Duplicate marked BAM files are indexed with samtools index and a summary table of BAM flags is generated with samtools flagstat. Neither step is necessary for our variant calling, but index files are required for several programs that take BAM inputs, and the flagstats reports are a convenient way to assess overall mapping quality (e.g. the percentage of mapped reads, the number of duplicates, mappings to more than one location). See table 1 for a comparison of mapping quality among different Littorina species.

 

 

SECTION: Variant calling
9.1. 3.1) mpileup:
This step estimates a genotype likelihood for each variant. mpileup files can take some time to generate. Splitting the genome into regions with -r CHROM:POS, speeds up the process by parallelising the job. Splitting is done by chromosome, splitting some of the larger chromosomes in half. The -a option tells bcftools to annotate the mpileup with additional quality scores. We add allele depth (AD), total depth (DP) and strand bias (SP) per site to the FORMAT field, and the allelic depth (AD) per individual to the INFO field.

 

SECTION: Variant calling
9.2. 3.2) Variant call:
The next step is to call variant sites with bcftools call. The -m option activates the multiallelic calling mode, -Oz compresses the output, and -f GQ,GP includes genotype quality (GQ) and genotype probability (GP) in the output. We recommend calling both variant and invariant sites (of sufficient quality), as invariant positions are needed to correctly calculate many population genetic statistics  (e.g. π and dxy). 

 
There are a few options to consider when calling variants. Downstream processes can be sped up by changing the output to be in binary call format (BCF) with -Ob. However, this will increase the file size. If space is limited, set -v to remove invariant sites from the output, but this limits the potential for some downstream analysis.
SECTION: Variant filtering
11. 4.1) Hard filters:
The goal is to delete entire positions from the VCF based on criteria that suggest the site was poorly sequenced or problematic. Hard filters can also be used to remove types of variants that are not of interest, such as indels or multiallelic sites. Below are some commands for filters that are commonly applied, but this list is not exhaustive. Different variant callers also compute different quality statistics, so be aware that the names and possible options vary if you are using a different caller (e.g., GATK). Short descriptions of the quality statistics should be listed in the VCF header.
SECTION: Variant filtering
11.1. 4.1.1) Remove indels and multallelic sites:
Firstly, we remove types of variants which are not interesting for our research. Typically for WGS analysis, indels and multiallelic variants are removed, but there is some evidence that they may contribute to evolutionary processes (Perini 2021). We opted for not just removing indels, but also SNPs within 5bp of them as these sites tend to be problematic due to errors in the realignment process. The -g 5:indel,other option removes sites around indels, while the -v snps keeps only SNPs. We also remove multiallelic sites by setting -M 2. Specifically, this option caps the number of alleles per site to two. Optionally, a minimum can be set with -m 2 to remove invariant sites.

 


SECTION: Variant filtering
11.2. 4.1.2) Total read depth per site:
Next we filter by total read depth per site (INFO/DP). This is the sum of reads across all samples. Only an upper limit is generally needed, as low read depth will be filtered by other steps (see soft filters). When depth is too high we recommend removing the whole site, as these can represent repeated sequences and misalignments of the reference genome. A common criterion is to drop sites with more than 2.5x the average coverage.

 

SECTION: Variant filtering
11.3. 4.1.2b) Setting a minimum total depth filter [conditional]
For high coverage calls including invariant sites you can set a lower limit to remove sites where there is a risk of calling an invariant site by mistake.  We recommend dropping sites with fewer reads than 14 x the number of samples. The parameter 14 is based on the distribution of variant and invariant sites in L. saxatilis data (Stankowski et al. 2024). 

Again, do not set  the lower INFO/DP filter for low coverage data. This will throw away too many good quality sites. We do not want to toss the baby with the bath water.

SECTION: Variant filtering
11.4. 4.1.3) mapping quality, genotype quality and strand-bias:
Three more steps are involved in hard filtering, mapping quality (MQ), site call quality (QUAL) and strand bias (SP) filters. All three use Phred quality scores, which correspond to the probability of an error. The Phred scale is logarithmic, so larger scores indicate a lower probability of error. For example, a Phred-score of 20 indicates a 1% change of an error and a Phred-score of 30 indicates a 0.1% chance. 

The first Phred-score is MQ, the average mapping quality at a site. Typically this should be set high to drop poorly mapped positions. Values between 30 and 40 are common. 

 
QUAL is the probability that the alternative allele call was wrong. A score of 30 is common.

 
Lastly, SP is the probability that one DNA strand is sequenced at a higher frequency than the other. Dropping SP > 3 is recommended as a light filter. Your threshold should be based on the distribution of scores (Fig. 2).

 

SECTION: Variant filtering
12. 4.2) Soft filters:
After we have arrived at a set of variants that we feel are of adequate quality, we will now soft filter individual genotypes to mask those that we do not trust. Soft filters will set genotypes that do not pass our filters to missing (./.) while genotypes that pass the filters remain unaffected.  

For bcftools the two soft filtered statistics are the genotype quality score (GQ) and depth of coverage (FMT/DP) per sample. GQ is Phred scored, thus GQ of 20 indicates a 1% chance that the call is incorrect for that sample. A GQ score of 30 is considered the gold standard, but might be overly conservative with low coverage data. 

FMT/DP is the depth from the format field of the VCF (i.e. the coverage for each sample). At least 2 reads need to be present to call a heterozygote in diploid data. However, at FMT/DP = 2 there is only a 50% chance that we have seen both alleles. 5 reads gives us a 93.8% chance. With 10 reads this goes up to 99.8%, but if the threshold is above the targeted coverage most sites will be dropped. In short, the higher thresholds are more accurate, but the appropriate choice depends on sequencing depth.

 

SECTION: Variant filtering
13. 4.3) Filter out missing data:
After setting low quality genotypes to missing, we need to remove sites with high missing data. The percentage of missing data at which we remove sites is up to the user to decide. A simple rule is that with more samples more missing data can be tolerated. Filters that remove sites with more than 10-20% missing genotypes are common.

 

SECTION: Variant filtering
14. 4.4) How do I choose filtering thresholds for my data?
Before and after applying a filter it is good practice to plot the distributions of key VCF statistics. There are no strict rules for choosing filters, only guidelines. Examples for some Littorina datasets are provided in Table 2.  Do not blindly follow our example filters (Table 2). They are a starting point, to get a feel for how scores are distributed. We strongly recommend looking at the quality scores of each VCF before filtering. One must use common sense, logic and the shapes of the distributions to decide the best thresholds. After filtering, it is useful to replot these distributions to ensure that the filter worked as expected. 

 
Quality scores can be extracted from a VCF with bcftools query. The results can then be plotted in R, or any other data analysis program. Trying this for the full data set is very time consuming as there is a lot of data to view. To speed things up, we recommend randomly downsampling a small proportion of SNPs using vcfrandomsample from the vcflib package (Garrison et al. 2022). For information on filtering invariant positions, see the supplementary information in Stankowski et al. 2024. 

 
bcftools query uses the -f option to query. This is followed by a string expression in quotation marks. See the full bcftools manual for details. We are extracting the chromosome name (CHROM), site position (POS) and the focal score. This last value can be set to score in the VCF. By default the score for each site (often site average) is extracted. Place square brackets around the value to get the score for each genotype.

 

 

 

 

 

For strand-bias we are looking at the average score per site. While we could download all scores then calculate the average, it is much faster to calculate the average beforehand. Below, we use the awk command to directly calculate the row averages from the bcftools query output. 

 

Our VCF does not automatically include the fraction of missing genotypes per site (FMISS). FMISS is added using the +fill-tags plugin. This plugin was introduced in version 1.2 of bcftools.

 

Since we are extracting scores, it is a good idea to also look at the distribution of allele frequencies. Although we will not filter these scores, the distribution can indicate possible problems with the data.

 
Once quality scores are extracted you can plot them to determine your filtering thresholds. These can then be compared to the values after filtering (Fig. 2). We show how to do this for total site depth in R script.

 

 
 
 
SECTION: Appendix 1: adjustments for different datasets
15. Our default pipeline is developed for whole genome shotgun reads, with the goal of producing a set of SNP genotypes for analysis, as this is the most common approach used in evolutionary genomics research. However, other types of sequencing data require modifications to our pipeline. Here we give general advice about how our pipeline can be modified for three common types of data: RAD-seq, PoolSeq, and Haplotagging.

SECTION: Appendix 1: adjustments for different datasets
16. RAD-seq:
	Restriction-site-associated DNA (RAD) sequencing is an older approach still widely used in population genetic studies (Puritz et al. 2014). It breaks DNA at specific restriction sites resulting in several thousand short reads per run. It is commonly used as a cheaper alternative to WGS. RAD-seq fragments the genome at restriction sites using specific adaptor sequences. Trimming RAD-reads requires special handling of these adaptors. We recommend ignoring adaptors in fastp (option ‘-A') and processing RAD-seq data with an established pipeline (e.g. stacks, Rochette et al., 2019).
SECTION: Appendix 1: adjustments for different datasets
17. PoolSeq:
	Pooled sequencing is a common approach for analysing allele frequencies among populations on a budget (Schlötterer et al. 2014). DNA samples are pooled together in even proportions across a population to create a single pooled sample, which is then sequenced at high coverage. A single pair of fastq files is generated for each population.
	
	PoolSeq and WGS-seq pipelines are similar. The major difference is that variant calling requires a program which can handle high “ploidy” (e.g. N ≥ 50). PoPoolation (Kofler et al. 2011) was specially designed to handle PoolSeq data. Filtering options are more limited with PoPoolation, as it only retains the statistics added to the mpileup. However, many of the filtering steps we have mentioned for VCFs can be applied to the mpileup and BAM files (see example in Morales et al. 2019).
SECTION: Appendix 1: adjustments for different datasets
18. Haplotagging:
	Haplotagging is a new method of sequencing that keeps linkage information among reads (Meier et al. 2021). DNA libraries are prepared using specialised beads marking long DNA fragments with barcodes. Barcoded molecules are then sheared and washed off the beads and amplified with PCR, before standard Illumina short-read sequencing. 

SamHaplotag is a pipeline specifically made to process haplotagged data (evolgenomics, 2022). In demultiplexing, the barcodes are encoded within the comments fields, using the 10xspoof.pl script.The reads are then trimmed (if necessary) and, the haplotag barcodes are converted using the 16BaseBCGen programme into generic 16-base barcodes with 7-base joins which can then be used as input for read mapping. We recommend using the EMA read mapper (Shajii et al. 2017) instead of  BWA, to keep barcode information, which improves downstream genotyping accuracy, phasing, and structural variant detection. Variant calling and filtering can proceed with the recommendations of our pipeline.
SECTION: Appendix 2: glossary
19.