QTLtools-cis(1)
π QTLtools-cis(1) Β· Bioinformatics tools π
β¨ NAME β¨
Okay bestie, the whole name is QTLtools cis, which is just cis QTL analysis π
π¦ SYNOPSIS π¦
Here's the vibe for how you call it π
QTLtools cis --vcf [in.vcf|in.vcf.gz|in.bcf|in.bed.gz] --bed
quantifications.bed.gz [--nominal float | --permute integer | --mapping
in.txt] --out output.txt [OPTIONS]
π DESCRIPTION π
Okay so this mode is all about finding cis (proximal) QTLs, the quantitative trait loci that affect a phenotype, and it does it with linear regression π. The whole method is written up here: <https://www.nature.com/articles/ncomms15452> π. The flow goes like this: first we regress out the covariates you give us from the phenotype data, then we run the linear regression between those phenotype residuals and the genotype. If you pass --normal and --cov at the same time, the residuals after covariate correction get rank normal transformed β¨. It also has an efficient permutation scheme that handles the differential multiple testing burden of each phenotype, which is so iconic π₯.
You've got three passes to pick from π§©. There's a nominal pass (--nominal threshold) that lists all the genotype-phenotype associations below a certain threshold π. There's a permutation pass (--permute no_of_permutations) that empirically characterizes the null distribution of associations for each phenotype separately, which then adjusts the nominal p-value of the best association for that phenotype π². And there's a conditional analysis pass (--mapping filename) that discovers multiple proximal QTLs with independent effects on a phenotype π.
Multiple molecular phenotypes can belong to higher order biological entities, like exons of genes, so QTLtools cis lets you group phenotypes to maximize the discoveries in those particular cases π«Ά. You can either aggregate the phenotypes in a group into a single phenotype via PCA (--grp-pca1) or by taking their mean (--grp-mean). Or you can directly use all the individual phenotypes in an extended permutation scheme that accounts for their number and correlation structure (--grp-best). In their experience, --grp-best outperforms the other options for expression QTLs (eQTLs) π§¬.
The conditional analysis pass is a whole moment π . It first uses permutations to derive a nominal p-value threshold per phenotype that varies and reflects the number of independent tests per cis-window. Then it uses a forward-backward stepwise regression to learn the number of independent signals per phenotype, determine the best candidate variant per signal, and assign all significant hits to the independent signal they relate to πΈ.
Real talk: linear regressions assume normally distributed data, so we highly recommend the --normal option. It rank normal transforms the phenotype quantifications so you don't get false positive associations from outliers π Trust me on this one, periodt π.
π OPTIONS π
Okay, here are the options, bestie π§ Required ones are flagged, and I kept every default and recommendation.
--vcf [in.vcf|in.bcf|in.vcf.gz|in.bed.gz]β Your genotypes in VCF/BCF format, or another molecular phenotype in BED format. If a variant's genotype FORMAT has aDSfield (the dosage calculated from genotype probabilities, e.g. after imputation), that's what gets used as the genotype. If there's only theGTfield in the genotype FORMAT, then that's used and it gets converted to a dosage. REQUIRED.--bed quantifications.bed.gzβ Your molecular phenotype quantifications in BED format. REQUIRED.--out output.txtβ The output file. REQUIRED.--cov covariates.txtβ The covariates you want to correct the phenotype data with π§Ό--normalβ Rank normal transforms the phenotype data so each phenotype is normally distributed. RECOMMENDED.--std-errβ Calculates and outputs the standard error of the beta (slope) π--window integerβ The size of the cis window flanking each phenotype's start position. DEFAULT=1000000. RECOMMENDED=1000000.--nominal floatβ Calculates the nominal p-value for the genotype-phenotype associations and prints out the ones that pass the threshold you give. Give1.0to print everything. Mutually exclusive with--permuteand--mapping.--permute integerβ Adjusts the best nominal p-value for this phenotype, accounting for the number of variants and the linkage disequilibrium in its cis-window. We recommend at least 1000 permutations for the final analysis, and in most cases you'll see diminishing returns when going over 5000. But if you're doing exploratory stuff like figuring out which/how many covariates to include, you can go as low as 100. Mutually exclusive with--nominaland--mapping. RECOMMENDED=1000.--mapping thresholds_filenameβ The conditional analysis π§© First you need to run a permutation analysis, then generate a thresholds file using therunFDR_cis.Rscript in the script directory. Mutually exclusive with--nominaland--permute.--grp-bestβ Corrects for multiple phenotypes within a phenotype group. Mutually exclusive with--grp-pca1and--grp-mean.--grp-pca1β Runs PCA on the phenotypes within a phenotype group and uses PC1 for association testing. Mutually exclusive with--grp-bestand--grp-mean.--grp-meanβ Averages the phenotypes within a group and uses the results for association testing. Mutually exclusive with--grp-bestand--grp-pca1.--chunk integer1 integer2β For parallelization π Divides the data intointeger2number of chunks and processes chunk numberinteger1. Chunk 0 will print a header. Mutually exclusive with--regionand--region-pair. The minimum number of chunks has to be at least the same number of chromosomes in the--bedfile.--region chr:start-endβ The genomic region to be processed πΊοΈ E.g.chr4:12334456-16334456, orchr5. Mutually exclusive with--chunkand--region-pair.--region-pair chr:start-end chr:start-endβ The genomic region for genotypes, followed by the region for phenotypes, to be processed. Mutually exclusive with--chunkand--region.
The --permute output file is where all the juicy results live π It's space separated, and bestie, which columns show up depends on the options you pick π We really recommend including chunk 0 so you get a header and nobody gets confused π«Ά
- Column 1:
phe_id|grp_idβ the phenotype ID, or the phenotype group ID if one of the grouping options is provided πΈ - Column 2:
phe_chrβ the phenotype's chromosome π§ - Column 3:
phe_fromβ where the phenotype starts π¦ - Column 4:
phe_toβ where the phenotype ends β¨ - Column 5:
phe_strdβ the phenotype's strand π- Column 5.1:
phe_id|ve_by_pc1|n_phe_in_grpβ only printed with--group-best|--group-pca1|--group-mean. It's the phenotype ID for--group-best, the variance explained by PC1 for--group-pca1, or the number of phenotypes in the group for--group-meanπ - Column 5.2:
n_phe_in_grpβ only printed with--group-pca1|--group-mean. The number of phenotypes in the group π
- Column 5.1:
- Column 6:
n_var_in_cisβ the number of variants in the cis window for this phenotype π - Column 7:
dist_phe_varβ the distance between the variant and the phenotype start positions π - Column 8:
var_idβ the ID of the most significant variant π - Column 9:
var_chrβ the most significant variant's chromosome π₯ - Column 10:
var_fromβ the start position of the most significant variant β - Column 11:
var_toβ the end position of the most significant variant β¨ - Column 12:
dof1β the number of degrees of freedom used to compute the p-values π¦ - Column 13:
dof2β the estimated number of degrees of freedom used in the beta approximation p-value calculations πΈ - Column 14:
bml1β the first shape parameter of the fitted beta distribution (alpha). These should be close to 1 π - Column 15:
bml2β the second shape parameter of the fitted beta distribution (beta). This one corresponds to the effective number of independent tests in the region π§ - Column 16:
nom_pvalβ the nominal p-value of the association between the most significant variant and the phenotype π - Column 17:
r_squaredβ the r squared of the linear regression π - Column 18:
slopeβ the beta (slope) of the linear regression π- Column 18.1:
slope_seβ the standard error of the beta. Only printed if--std-erris provided π«Ά
- Column 18.1:
- Column 19:
adj_emp_pvalβ the adjusted empirical p-value from permutations. This is the adjusted p-value not using the beta approximation, and it's literally calculated as:
(number of p-values observed during permutations that were smaller than or equal to the nominal p-value + 1) / (number of permutations + 1)
The most significant p-value you could possibly get is 1 / (number of permutations + 1) π
- Column 20:
adj_beta_pvalβ the adjusted empirical p-value given by the fitted beta distribution π
We strongly recommend using this adjusted p-value in any downstream analysis. Seriously, bestie, use this one π
πΊοΈ --mapping output file
okay so this is the mapping file πΊοΈ it's space-separated, and some columns only show up depending on your options π we recommend including chunk 0 so you get a header and nobody gets confused π
- Column 1:
phe_id|grp_id: the phenotype ID, or the phenotype group ID if you used one of the grouping options π§ - Column 2:
phe_chr: the phenotype's chromosome πΈ - Column 3:
phe_from: where the phenotype starts π¦ - Column 4:
phe_to: where the phenotype ends π - Column 5:
phe_strd: the phenotype's strand π - Column 5.1:
phe_id|ve_by_pc1|n_phe_in_grp: only shows up with--group-best|--group-pca1|--group-mean. It's the phenotype ID, the variance explained by PC1, or the number of phenotypes in the group, for--group-best,--group-pca1, and--group-meanrespectively β¨ - Column 5.2:
n_phe_in_grp: only shows up with--group-pca1|--group-mean. It's the number of phenotypes in the phenotype group π«Ά - Column 6:
n_var_in_cis: how many variants are in the cis window for this phenotype π - Column 7:
dist_phe_var: the distance between the variant and the phenotype start positions π - Column 8:
var_id: the ID of the most significant variant π - Column 9:
var_chr: the most significant variant's chromosome πΈ - Column 10:
var_from: the start position of the most significant variant π¦ - Column 11:
var_to: the end position of the most significant variant π - Column 12:
rank: the rank of the association. This tells you whether the variant got mapped to the best signal (rank=0), the second best (rank=1), and so on π₯ Because of that, the highest rank for a given phenotype tells you how many independent signals there are (e.g.rank=2means 3 independent signals) π§ - Column 13:
fwd_pval: the nominal forward p-value of the association between the most significant variant and the phenotype π - Column 14:
fwd_r_squared: the r squared of the forward linear regression π - Column 15:
fwd_slope: the beta (slope) of the forward linear regression π - Column 15.1:
fwd_slope_se: the standard error of the forward beta. Only printed if--std-erris provided π - Column 16:
fwd_best_hit: whether or not this variant was the forward most significant variant π - Column 17:
fwd_sig: whether this variant was significant. Currently all variants are significant, so this one is redundant π - Column 18:
bwd_pval: the nominal backward p-value of the association between the most significant variant and the phenotype π - Column 19:
bwd_r_squared: the r squared of the backward linear regression π - Column 20:
bwd_slope: the beta (slope) of the backward linear regression π - Column 20.1:
bwd_slope_se: the standard error of the backward beta. Only printed if--std-erris provided π - Column 21:
bwd_best_hit: whether or not this variant was the backward most significant variant π - Column 22:
bwd_sig: whether this variant was significant. Currently all variants are significant, so this one is redundant π
β¨ NOMINAL ANALYSIS EXAMPLES β¨
- Nominal pass, correcting for technical covariates, rank normal transforming the phenotype, printing out associations with a p-value
<= 0.01on chromosome 22 between 17000000 and 18000000 bp, and excluding some samples (see QTLtools (1)) πΈ:
QTLtools cis --vcf genotypes.chr22.vcf.gz --bed genes.50percent.chr22.bed.gz --cov genes.covariates.pc50.txt.gz --nominal 0.01 --region chr22:17000000-18000000 --normal --out nominals.txt --exclude-samples sample_names_to_exclude.txt
- Nominal pass with parallelization, correcting for technical covariates, rank normal transforming the phenotype, and printing out associations with a p-value
<= 0.01. To make parallelization on a compute cluster easier, we built an option to run the analysis in chunks of molecular phenotypes π§ For instance, to run the analysis on chunk 12 when splitting the example data set into 20 chunks, run:
QTLtools cis --vcf genotypes.chr22.vcf.gz --bed genes.50percent.chr22.bed.gz --cov genes.covariates.pc50.txt.gz --nominal 0.01 --chunk 12 20 --normal --out nominals_12_20.txt
- If you want to submit the whole analysis as 20 jobs on a compute cluster, just run this (
qsubneeds to be swapped out for the job submission system you use [bsub, psub, etc...]) π₯:
for j in $(seq 0 20); do
echo "QTLtools cis --vcf genotypes.chr22.vcf.gz --bed genes.50percent.chr22.bed.gz --cov genes.covariates.pc50.txt.gz --nominal 0.01 --chunk $j 20 --normal --out nominals_$j\_20.txt" | qsub
done
β¨ PERMUTATION ANALYSIS EXAMPLES β¨
- Permutation pass, correcting for technical covariates, rank normal transforming the phenotype, and running 1000 permutations with a specific random seed on chromosome 22 between 17000000 and 18000000 bp π:
QTLtools cis --vcf genotypes.chr22.vcf.gz --bed genes.50percent.chr22.bed.gz --cov genes.covariates.pc50.txt.gz --permute 1000 --region chr22:17000000-18000000 --normal --seed 1354145 --out permutation.txt
- Permutation pass with parallelization, correcting for technical covariates, rank normal transforming the phenotype, and running 5000 permutations. To make parallelization on a compute cluster easier, we built an option to run the analysis in chunks of molecular phenotypes π§ For instance, to run the analysis on chunk 12 when splitting the example data set into 20 chunks, run:
QTLtools cis --vcf genotypes.chr22.vcf.gz --bed genes.50percent.chr22.bed.gz --cov genes.covariates.pc50.txt.gz --permute 5000 --chunk 12 20 --normal --out permutations_12_20.txt
- If you want to submit the whole analysis as 20 jobs on a compute cluster, just run this (
qsubneeds to be swapped out for the job submission system you use [bsub, psub, etc...]) π₯:
for j in $(seq 0 20); do
echo "QTLtools cis --vcf genotypes.chr22.vcf.gz --bed genes.50percent.chr22.bed.gz --cov genes.covariates.pc50.txt.gz --permute 5000 --chunk $j 20 --normal --out permutations_$j\_20.txt" | qsub
done
- When your phenotypes in the BED file are grouped, you can run a permutation pass at the phenotype group level to discover group-level QTLs π:
QTLtools cis --vcf genotypes.chr22.vcf.gz --bed exons.50percent.chr22.bed.gz --cov genes.covariates.pc50.txt.gz --permute 1000 --normal --grp-best --out permutation.group.txt
β¨ CONDITIONAL ANALYSIS EXAMPLE β¨
Conditional analysis to discover independent signals π¦
- First we need to run a permutation analysis (see previous section), then calculate the nominal p-value threshold for each gene. Here an FDR of 5% is given as an example π :
cat permutations_*.txt | gzip -c > permutations_all.txt.gz
Rscript ./script/qtltools_runFDR_cis.R permutations_all.txt.gz 0.05 permutations_all
- Now you can proceed with the actual conditional analysis. Here we split into 20 chunks, and when they're all complete, concatenate the results π«Ά:
for j in $(seq 0 20); do
echo "QTLtools cis --vcf genotypes.chr22.vcf.gz --bed genes.50percent.chr22.bed.gz --cov genes.covariates.pc50.txt.gz --mapping permutations_all.thresholds.txt --chunk $j 20 --normal --out conditional_$j\_20.txt" | qsub
done
cat conditional_*.txt > conditional_all.txt
- If you're interested in the most significant variants per independent signal, you can filter the results using the backward p-value π:
awk '{ if ($21 == 1) print $0 }' conditional_all.txt > conditional_top_variants.txt
β¨ SEE ALSO β¨
QTLtools(1)π- QTLtools website:
https://qtltools.github.io/qtltoolsπ
β¨ BUGS β¨
- Heads up, bestie π Versions up to and including
1.2have a bug when reading missing genotypes inVCF/BCFfiles. It hits variants with aDSfield in their genotype'sFORMATand a missing genotype (DSfield is.) in one of the samples. When that happens, genotypes for all the samples get set to missing, which effectively removes that variant from the analyses. Not it π
Found a bug that isn't on this list? Report it at https://github.com/qtltools/qtltools π«Ά
π CITATION π
If you cite QTLtools, this is the one πβ¨
Delaneau, O., Ongen, H., Brown, A. et al. A complete tool set for
molecular QTL discovery and analysis. Nat Commun 8, 15452 (2017).
<https://doi.org/10.1038/ncomms15452>
π AUTHORS π
The girlies behind this tool are Olivier Delaneau (olivier.delaneau@gmail.com) and Halit Ongen (halitongen@gmail.com) ππ
That's the whole page, bestie! π¦ It came from QTLtools-v1.3, dated 06 May 2020, and lives under QTLtools-cis(1) πβ¨
π¦ where this page comes from
- debian bookworm: qtltools 1.3.1+dfsg-4 Β· GPL-3.0-or-later
- debian trixie: qtltools 1.3.1+dfsg-4+b3 Β· GPL-3.0-or-later
- ubuntu jammy: qtltools 1.3.1+dfsg-2build2 Β· GPL-3.0-or-later
- ubuntu noble: qtltools 1.3.1+dfsg-4build3 Β· GPL-3.0-or-later
- ubuntu questing: qtltools 1.3.1+dfsg-4build6
- ubuntu resolute: qtltools 1.3.1+dfsg-4build7 Β· GPL-3.0-or-later
- ubuntu stonking: qtltools 1.3.1+dfsg-6 Β· GPL-3.0-or-later
- π girlified by claude-haiku-5-5 on : a language model's rewrite of the original, under its terms