<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Posts | Pascal GP Martin</title><link>https://pascal-martin.netlify.app/post/</link><atom:link href="https://pascal-martin.netlify.app/post/index.xml" rel="self" type="application/rss+xml"/><description>Posts</description><generator>Source Themes Academic (https://sourcethemes.com/academic/)</generator><language>en-us</language><image><url>https://pascal-martin.netlify.app/media/PhotoPgpmartin.jpg</url><title>Posts</title><link>https://pascal-martin.netlify.app/post/</link></image><item><title>Plotting SRA database growth</title><link>https://pascal-martin.netlify.app/post/plotting-sra-database-growth/</link><pubDate>Mon, 06 Dec 2021 00:00:00 +0000</pubDate><guid>https://pascal-martin.netlify.app/post/plotting-sra-database-growth/</guid><description>&lt;p>The
&lt;a href="https://www.ncbi.nlm.nih.gov/sra/" target="_blank" rel="noopener">Sequence Read Archive&lt;/a> is NCBI&amp;rsquo;s database for high throughput sequencing data and the largest public repository for such data.&lt;br>
The data on the growth of the database is available
&lt;a href="https://www.ncbi.nlm.nih.gov/sra/docs/sragrowth/" target="_blank" rel="noopener">here&lt;/a>&lt;/p>
&lt;h2 id="load-packages">Load packages&lt;/h2>
&lt;pre>&lt;code class="language-r">suppressPackageStartupMessages(library(magrittr))
suppressPackageStartupMessages(library(httr))
suppressPackageStartupMessages(library(ggplot2))
&lt;/code>&lt;/pre>
&lt;h2 id="function-to-make-nicer-axis-labels">Function to make nicer axis labels&lt;/h2>
&lt;pre>&lt;code class="language-r">scientific_10 &amp;lt;- function(x) {
xx &amp;lt;- dplyr::case_when(x&amp;gt;=0 &amp;amp; x&amp;lt;=100 ~ as.character(x),
x&amp;gt;100 &amp;amp; log10(x)%%1==0 ~ gsub(&amp;quot;.+e\\+&amp;quot;, &amp;quot;10^&amp;quot;, scales::scientific_format()(x)),
TRUE ~ gsub(&amp;quot;e\\+&amp;quot;, &amp;quot; %*% 10^&amp;quot;, scales::scientific_format()(x)))
parse(text = xx)
}
&lt;/code>&lt;/pre>
&lt;h2 id="download-the-data-in--r">Download the data in R&lt;/h2>
&lt;pre>&lt;code class="language-r">sraurl &amp;lt;- &amp;quot;https://www.ncbi.nlm.nih.gov/Traces/sra/sra_stat.cgi&amp;quot;
sra &amp;lt;- httr::GET(url=sraurl) %&amp;gt;%
httr::content(encoding=&amp;quot;UTF-8&amp;quot;)
sra$date &amp;lt;- as.Date(sra$date, format = &amp;quot;%m/%d/%Y&amp;quot;)
&lt;/code>&lt;/pre>
&lt;h2 id="plot-with-linear-scale">Plot with linear scale&lt;/h2>
&lt;pre>&lt;code class="language-r">sra %&amp;gt;%
dplyr::select(date, bases, open_access_bases) %&amp;gt;%
tidyr::pivot_longer(cols = 2:3, names_to = &amp;quot;type&amp;quot;, values_to = &amp;quot;terabases&amp;quot;) %&amp;gt;%
dplyr::mutate(terabases = terabases / 1e12) %&amp;gt;%
dplyr::mutate(type = dplyr::case_when(type == &amp;quot;bases&amp;quot; ~ &amp;quot;total bases&amp;quot;,
type == &amp;quot;open_access_bases&amp;quot; ~ &amp;quot;open access bases&amp;quot;)) %&amp;gt;%
ggplot(mapping = aes(x = date, y = terabases, color = type)) +
geom_line(size = 1.5) +
scale_color_manual(name = NULL,
values = c(&amp;quot;total bases&amp;quot; = &amp;quot;darkred&amp;quot;,
&amp;quot;open access bases&amp;quot; = &amp;quot;darkblue&amp;quot;)) +
scale_y_continuous(labels = scientific_10 ) +
labs(x = &amp;quot;Year&amp;quot;, y = expression( Terabases~(10^12) ),
title = &amp;quot;Growth of Sequence Read Archive database&amp;quot;) +
theme_bw() +
NULL
&lt;/code>&lt;/pre>
&lt;figure id="figure-growth-of-sequence-read-archive-database">
&lt;a data-fancybox="" href="https://pascal-martin.netlify.app/post/plotting-sra-database-growth/SRA_growth_linear_hu3ef39b37fa31e7048ea9b93cc5e6ae1a_27646_2000x2000_fit_lanczos_3.png" data-caption="Growth of Sequence Read Archive database">
&lt;img data-src="https://pascal-martin.netlify.app/post/plotting-sra-database-growth/SRA_growth_linear_hu3ef39b37fa31e7048ea9b93cc5e6ae1a_27646_2000x2000_fit_lanczos_3.png" class="lazyload" alt="" width="700" height="432">
&lt;/a>
&lt;figcaption>
Growth of Sequence Read Archive database
&lt;/figcaption>
&lt;/figure>
&lt;h2 id="plot-with-log-scale">Plot with log scale&lt;/h2>
&lt;pre>&lt;code class="language-r">sra %&amp;gt;%
dplyr::select(date, bases, open_access_bases) %&amp;gt;%
tidyr::pivot_longer(cols = 2:3, names_to = &amp;quot;type&amp;quot;, values_to = &amp;quot;bases&amp;quot;) %&amp;gt;%
dplyr::mutate(type = dplyr::case_when(type == &amp;quot;bases&amp;quot; ~ &amp;quot;total bases&amp;quot;,
type == &amp;quot;open_access_bases&amp;quot; ~ &amp;quot;open access bases&amp;quot;)) %&amp;gt;%
ggplot(mapping = aes(x = date, y = bases, color = type)) +
geom_line(size = 1.5) +
scale_color_manual(name = NULL,
values = c(&amp;quot;total bases&amp;quot; = &amp;quot;darkblue&amp;quot;,
&amp;quot;open access bases&amp;quot; = &amp;quot;darkred&amp;quot;)) +
scale_y_log10(labels = scientific_10 ) +
labs(x = &amp;quot;Year&amp;quot;, y = &amp;quot;bases&amp;quot; ,
title = &amp;quot;Growth of Sequence Read Archive database&amp;quot;) +
theme_bw() +
NULL
&lt;/code>&lt;/pre>
&lt;figure id="figure-growth-log-of-sequence-read-archive-database">
&lt;a data-fancybox="" href="https://pascal-martin.netlify.app/post/plotting-sra-database-growth/SRA_growth_log_hub5af44928a2e526885a555bbc9e13762_26355_2000x2000_fit_lanczos_3.png" data-caption="Growth (log) of Sequence Read Archive database">
&lt;img data-src="https://pascal-martin.netlify.app/post/plotting-sra-database-growth/SRA_growth_log_hub5af44928a2e526885a555bbc9e13762_26355_2000x2000_fit_lanczos_3.png" class="lazyload" alt="" width="700" height="432">
&lt;/a>
&lt;figcaption>
Growth (log) of Sequence Read Archive database
&lt;/figcaption>
&lt;/figure></description></item><item><title>Blastn output format 6</title><link>https://pascal-martin.netlify.app/post/blastn-output-format-6/</link><pubDate>Fri, 12 Mar 2021 00:00:00 +0000</pubDate><guid>https://pascal-martin.netlify.app/post/blastn-output-format-6/</guid><description>&lt;p>&lt;strong>See also:&lt;/strong>&lt;/p>
&lt;ul>
&lt;li>
&lt;a href="https://www.ncbi.nlm.nih.gov/books/NBK279690/pdf/Bookshelf_NBK279690.pdf" target="_blank" rel="noopener">Blast documentation&lt;/a>&lt;/li>
&lt;li>
&lt;a href="http://www.metagenomics.wiki/tools/blast/blastn-output-format-6" target="_blank" rel="noopener">Blast on Metagenomics Wiki&lt;/a>&lt;/li>
&lt;li>&lt;code>blastn -help&lt;/code> and check &lt;code>-outfmt&lt;/code> formatting option&lt;/li>
&lt;/ul>
&lt;h2 id="prepare-the-database">Prepare the database&lt;/h2>
&lt;p>Only needed if reference sequences are going to be used frequently&lt;/p>
&lt;pre>&lt;code class="language-bash">makeblastdb \
-in myRefSeqs.fasta \
-out &amp;quot;My/Folder/myRefSeqs_blastdb&amp;quot; \
-dbtype &amp;quot;nucl&amp;quot; \
--parse_seqids \
-logfile My/Folder/logFile.log
&lt;/code>&lt;/pre>
&lt;h2 id="run-blast">Run Blast&lt;/h2>
&lt;p>&lt;code>-num_alignment&lt;/code> default is &lt;code>250&lt;/code>. Modify it if more alignments are expected&lt;br>
&lt;code>-outfmt&lt;/code> sets the output format&lt;/p>
&lt;pre>&lt;code class="language-bash">blastn \
-task megablast \
-query InputSequence.fasta \
-db &amp;quot;My/Folder/myRefSeqss_blastdb&amp;quot; \
-out My/Output/Folder/InputSeq_vs_RefSeqs.res \
-outfmt 6 \
-num_alignments 10000000
&lt;/code>&lt;/pre>
&lt;p>Run blast with 2 fasta sequences:&lt;/p>
&lt;pre>&lt;code class="language-bash">blastn \
-query genes.fasta \
-subject genome.fasta \
-outfmt 6
&lt;/code>&lt;/pre>
&lt;p>Default value for &lt;code>-outfmt 6&lt;/code> corresponds to &lt;code>-outfmt &amp;quot;6 qseqid sseqid pident length mismatch gapopen qstart qend sstart send evalue bitscore&amp;quot;&lt;/code>&lt;/p>
&lt;h2 id="output">Output&lt;/h2>
&lt;p>Column headers:&lt;br>
&lt;span style="color:blue">&lt;code>qseqid sseqid pident length mismatch gapopen qstart qend sstart send evalue bitscore&lt;/code> &lt;/span>&lt;br>
In R:&lt;/p>
&lt;pre>&lt;code class="language-r">c(&amp;quot;qseqid&amp;quot;,&amp;quot;sseqid&amp;quot;, &amp;quot;pident&amp;quot;, &amp;quot;length&amp;quot;,
&amp;quot;mismatch&amp;quot;, &amp;quot;gapopen&amp;quot;, &amp;quot;qstart&amp;quot;, &amp;quot;qend&amp;quot;,
&amp;quot;sstart&amp;quot;, &amp;quot;send&amp;quot;, &amp;quot;evalue&amp;quot;, &amp;quot;bitscore&amp;quot;)
&lt;/code>&lt;/pre>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th style="text-align:right">Col&lt;/th>
&lt;th style="text-align:left">name&lt;/th>
&lt;th style="text-align:left">Description&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td style="text-align:right">1.&lt;/td>
&lt;td style="text-align:left">&lt;span style="color:blue">qseqid&lt;/span>&lt;/td>
&lt;td style="text-align:left">query (e.g., unknown gene) sequence id&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align:right">2.&lt;/td>
&lt;td style="text-align:left">&lt;span style="color:blue">sseqid&lt;/span>&lt;/td>
&lt;td style="text-align:left">subject (e.g., reference genome) sequence id&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align:right">3.&lt;/td>
&lt;td style="text-align:left">&lt;span style="color:blue">pident&lt;/span>&lt;/td>
&lt;td style="text-align:left">percentage of identical matches&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align:right">4.&lt;/td>
&lt;td style="text-align:left">&lt;span style="color:blue">length&lt;/span>&lt;/td>
&lt;td style="text-align:left">alignment length (sequence overlap)&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align:right">5.&lt;/td>
&lt;td style="text-align:left">&lt;span style="color:blue">mismatch&lt;/span>&lt;/td>
&lt;td style="text-align:left">number of mismatches&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align:right">6.&lt;/td>
&lt;td style="text-align:left">&lt;span style="color:blue">gapopen&lt;/span>&lt;/td>
&lt;td style="text-align:left">number of gap openings&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align:right">7.&lt;/td>
&lt;td style="text-align:left">&lt;span style="color:blue">qstart&lt;/span>&lt;/td>
&lt;td style="text-align:left">start of alignment in query&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align:right">8.&lt;/td>
&lt;td style="text-align:left">&lt;span style="color:blue">qend&lt;/span>&lt;/td>
&lt;td style="text-align:left">end of alignment in query&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align:right">9.&lt;/td>
&lt;td style="text-align:left">&lt;span style="color:blue">sstart&lt;/span>&lt;/td>
&lt;td style="text-align:left">start of alignment in subject&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align:right">10.&lt;/td>
&lt;td style="text-align:left">&lt;span style="color:blue">send&lt;/span>&lt;/td>
&lt;td style="text-align:left">end of alignment in subject&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align:right">11.&lt;/td>
&lt;td style="text-align:left">&lt;span style="color:blue">evalue&lt;/span>&lt;/td>
&lt;td style="text-align:left">expect value&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align:right">12.&lt;/td>
&lt;td style="text-align:left">&lt;span style="color:blue">bitscore&lt;/span>&lt;/td>
&lt;td style="text-align:left">bit score&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table></description></item><item><title>Generate random genes as GRanges</title><link>https://pascal-martin.netlify.app/post/generate-random-genes-as-granges/</link><pubDate>Sun, 09 Dec 2018 00:00:00 +0000</pubDate><guid>https://pascal-martin.netlify.app/post/generate-random-genes-as-granges/</guid><description>&lt;h2 id="generating-random-genome-annotations">Generating random genome annotations&lt;/h2>
&lt;p>For different purposes, I often need to create random gene/features annotations.
I usually need these annotations as a &lt;code>GRanges&lt;/code> object (see the
&lt;a href="http://bioconductor.org/packages/release/bioc/html/GenomicRanges.html" target="_blank" rel="noopener">GenomicRanges package&lt;/a>).&lt;br>
I searched a bit on the internet but couldn&amp;rsquo;t really find what I was looking for.&lt;/p>
&lt;p>I want to be able to control the following parameters:&lt;/p>
&lt;ul>
&lt;li>Number of genes&lt;/li>
&lt;li>Gene sizes (~gaussian distribution with upper and lower bounds as parameters)&lt;/li>
&lt;li>Number of chromosomes&lt;/li>
&lt;li>Chromosomes' length&lt;/li>
&lt;/ul>
&lt;p>I will assign to each chromosome a number of gene that is proportional to the chromosome length (so all chromosome have ~equal gene densities).&lt;/p>
&lt;p>First I need 2 functions:&lt;/p>
&lt;ol>
&lt;li>A function that generates random (and unique) gene names&lt;/li>
&lt;li>A function that generates gene lengths (or &amp;lsquo;sizes&amp;rsquo;) within defined boundaries&lt;/li>
&lt;/ol>
&lt;h3 id="function-to-generate-random-gene-names">Function to generate random gene names&lt;/h3>
&lt;p>I basically copy/pasted a solution found on this
&lt;a href="https://stackoverflow.com/questions/29652356/generate-unique-alphanumeric-ids" target="_blank" rel="noopener">stackoverflow post&lt;/a>. I just modified it slightly to ony allow letters (and not numbers) in gene names in order to simplify the definition of the length (number of characters) of gene names, which will be automatically defined based on the gene number.&lt;/p>
&lt;pre>&lt;code class="language-r">idGenerator &amp;lt;- function(n, lengthId) {
idList &amp;lt;- stringi::stri_rand_strings(n,
lengthId,
pattern = &amp;quot;[A-Za-z]&amp;quot;)
while(any(duplicated(idList))) {
idList[which(duplicated(idList))] &amp;lt;-
stringi::stri_rand_strings(sum(duplicated(idList), na.rm = TRUE),
lengthId,
pattern = &amp;quot;[A-Za-z]&amp;quot;)
}
return(idList)
}
&lt;/code>&lt;/pre>
&lt;h3 id="function-to-generate-random-gene-widthsizes">Function to generate random gene width/sizes&lt;/h3>
&lt;p>Gene size distribution heavily depends on the species. For example here is the distribution of gene annotations for 6 species:&lt;/p>
&lt;pre>&lt;code class="language-r">#Load libraries
library(tidyverse)
library(TxDb.Hsapiens.UCSC.hg38.knownGene)
library(TxDb.Athaliana.BioMart.plantsmart25)
library(TxDb.Dmelanogaster.UCSC.dm6.ensGene)
library(TxDb.Mmusculus.UCSC.mm10.ensGene)
library(TxDb.Scerevisiae.UCSC.sacCer3.sgdGene)
library(TxDb.Celegans.UCSC.ce6.ensGene)
txdb &amp;lt;- list()
txdb[[&amp;quot;hg38&amp;quot;]] &amp;lt;- TxDb.Hsapiens.UCSC.hg38.knownGene
txdb[[&amp;quot;mm10&amp;quot;]] &amp;lt;- TxDb.Mmusculus.UCSC.mm10.ensGene
txdb[[&amp;quot;dm6&amp;quot;]] &amp;lt;- TxDb.Dmelanogaster.UCSC.dm6.ensGene
txdb[[&amp;quot;ce6&amp;quot;]] &amp;lt;- TxDb.Celegans.UCSC.ce6.ensGene
txdb[[&amp;quot;tair10&amp;quot;]] &amp;lt;- TxDb.Athaliana.BioMart.plantsmart25
txdb[[&amp;quot;sacSer3&amp;quot;]] &amp;lt;- TxDb.Scerevisiae.UCSC.sacCer3.sgdGene
#Get gene size and arange as a data.frame
gnw &amp;lt;- reshape2::melt(lapply(txdb,
function(x) width(genes(x))),
value.name = &amp;quot;GeneSize&amp;quot;) %&amp;gt;%
dplyr::mutate(Species = factor(L1,
levels = names(txdb),
ordered = TRUE))
# Personalize colors and labels
mycols = viridis::viridis(8)[-c(1,8)]
names(mycols) &amp;lt;- names(txdb)
mylabs &amp;lt;- c(&amp;quot;Homo sapiens (hg38)&amp;quot;, &amp;quot;Mus musculus (mm10)&amp;quot;,
&amp;quot;Drosophila melaogaster (dm6)&amp;quot;, &amp;quot;Caenorhabditis elegans (cer6)&amp;quot;,
&amp;quot;Arabidopsis thaliana (TAIR10)&amp;quot;, &amp;quot;Saccharomyces cerevisiae (sacCer3)&amp;quot;)
names(mylabs) &amp;lt;- names(txdb)
# Plot distributions:
ggplot(gnw, aes(x=log10(GeneSize), fill=Species)) +
geom_histogram(aes(y=..density..),
colour=&amp;quot;black&amp;quot;, fill=&amp;quot;lightgrey&amp;quot;) +
geom_density(alpha=.3) +
scale_fill_manual(values = mycols,
labels = mylabs) +
scale_x_continuous(breaks = c(2, 4, 6),
labels = c(&amp;quot;100bp&amp;quot;, &amp;quot;10Kb&amp;quot;, &amp;quot;1Mbp&amp;quot;)) +
labs(x = &amp;quot;Gene Size (log scale)&amp;quot;,
y = &amp;quot;Density&amp;quot;) +
theme_bw() +
theme(panel.grid.minor = element_blank()) +
facet_wrap(vars(Species), nrow=3)
&lt;/code>&lt;/pre>
&lt;figure id="figure-gene-size-distribution-in-6-species">
&lt;a data-fancybox="" href="https://pascal-martin.netlify.app/media/GeneSizeDistribution_6species.png" data-caption="Gene Size Distribution in 6 species">
&lt;img src="https://pascal-martin.netlify.app/media/GeneSizeDistribution_6species.png" alt="" >
&lt;/a>
&lt;figcaption>
Gene Size Distribution in 6 species
&lt;/figcaption>
&lt;/figure>
&lt;p>Although it probably does not reflect a &amp;ldquo;natural&amp;rdquo; situation, I decided to define gene sizes based on a Gaussian distribution with a choice of a minimum and a maximum gene size.&lt;/p>
&lt;pre>&lt;code class="language-r">widthGenerator &amp;lt;- function(n, minWidth, maxWidth) {
if (maxWidth&amp;lt;=minWidth) stop(&amp;quot;maxWidth should be &amp;lt; minWidth&amp;quot;)
meanWidth &amp;lt;- minWidth + sqrt(maxWidth*minWidth) # take geometrical mean to limit the impact of high maxWidth
sdWidth &amp;lt;- floor((maxWidth-meanWidth)/3)
wdList &amp;lt;- round(rnorm(n, meanWidth, sdWidth))
isOutOfRange &amp;lt;- (wdList&amp;lt;minWidth | wdList&amp;gt;maxWidth)
while(any(isOutOfRange)) {
wdList[isOutOfRange] &amp;lt;- round(rnorm(sum(isOutOfRange),
meanWidth,
sdWidth))
isOutOfRange &amp;lt;- (wdList&amp;lt;minWidth | wdList&amp;gt;maxWidth)
}
return(wdList)
}
&lt;/code>&lt;/pre>
&lt;p>Here is what we generate with some relatively usual parameters (gene size betwen 100bp and 100Kb):&lt;/p>
&lt;pre>&lt;code class="language-r">df &amp;lt;- data.frame(GeneSize = widthGenerator(1e4, 100, 1e5))
ggplot(df, aes(x=log10(GeneSize))) +
geom_histogram(aes(y=..density..),
colour=&amp;quot;black&amp;quot;, fill=&amp;quot;lightgrey&amp;quot;) +
geom_density(alpha=.3, fill = &amp;quot;darkcyan&amp;quot;) +
scale_x_continuous(limits = c(1.2, 6.8),
breaks = c(2, 3, 4, 5, 6),
labels = c(&amp;quot;100bp&amp;quot;, &amp;quot;1kb&amp;quot;, &amp;quot;10kb&amp;quot;, &amp;quot;100kb&amp;quot;, &amp;quot;1Mb&amp;quot;)) +
labs(x = &amp;quot;Gene Size (log scale)&amp;quot;,
y = &amp;quot;Density&amp;quot;) +
theme_bw() +
theme(panel.grid.minor = element_blank())
&lt;/code>&lt;/pre>
&lt;p>&lt;img src="https://pascal-martin.netlify.app/post/2018-12-09-generate-random-genes-as-granges_files/figure-html/test widthGenerator-1.png" width="672" />&lt;/p>
&lt;h3 id="function-to-generate-random-genes">Function to generate random genes&lt;/h3>
&lt;p>Now the function that generates random genes as GRanges, using the 2 previous functions above:&lt;/p>
&lt;pre>&lt;code class="language-r">CreateGR &amp;lt;- function(ng=1e4, nchr=1, chromlength=1e4, widthMin=100, widthMax=1e4) {
## ng: number of genes
## nchr: number of chromosomes
## withMin/WidthMax: min/max gene size
## chromLength: vector of chromosome lengths
# Check
if (length(chromlength) != nchr) {
stop(&amp;quot;length(chromlength) is not equal to number of chromosomes (nchr)&amp;quot;)
}
#Number of genes on each chromosome
##Proportion of the genome for each chromosome
ChromProp &amp;lt;- chromlength/sum(chromlength)
##Number of genes per chromosome
GeneNumberByChr &amp;lt;- round(ChromProp*ng,0)
if (sum(GeneNumberByChr) != ng) {
GeneNumberByChr[1] &amp;lt;- GeneNumberByChr[1] + ng - sum(GeneNumberByChr)
}
#Chromosomes
chrNames &amp;lt;- paste0(&amp;quot;chr&amp;quot;, 1:nchr)
gnChr &amp;lt;- S4Vectors::Rle(rep(chrNames,
times=GeneNumberByChr))
#Strands
gnStrand &amp;lt;- S4Vectors::Rle(sample(c(&amp;quot;+&amp;quot;, &amp;quot;-&amp;quot;),
size = ng,
replace = TRUE))
#Ranges
##Gene names
gnLength &amp;lt;- ceiling(log(ng) / log(26)) + 1
gnNames &amp;lt;- idGenerator(ng, gnLength)
## start values (even with MaxWidth the genes won't go beyond chromosome borders)
gnStart &amp;lt;- unlist(mapply(sample,
lapply(chromlength,
function(x){(widthMax+1):(x-widthMax-1)}),
GeneNumberByChr,
list(&amp;quot;replace&amp;quot; = TRUE)),
use.names = FALSE)
#Gene widths
gnWidth &amp;lt;- widthGenerator(ng,
maxWidth=widthMax,
minWidth=widthMin)
GR &amp;lt;- GenomicRanges::GRanges(seqnames = gnChr,
ranges = IRanges::IRanges(start = gnStart,
width = gnWidth,
names = gnNames),
strand = gnStrand)
GenomeInfoDb::seqinfo(GR) &amp;lt;- GenomeInfoDb::Seqinfo(seqnames = chrNames,
seqlengths = chromlength,
isCircular = rep(FALSE, length(chrNames)),
genome = &amp;quot;mock&amp;quot;)
return(GR)
}
&lt;/code>&lt;/pre>
&lt;p>Using the following parameters, the function generates a &lt;code>GRanges&lt;/code> in ~30 nanoseconds:&lt;/p>
&lt;pre>&lt;code class="language-r">chromSizes &amp;lt;- c(30427671, 19698289, 23459830, 18585056, 26975502) # from A. thaliana genome
CreateGR(1e5, nchr=5, chromlength=chromSizes)
&lt;/code>&lt;/pre>
&lt;pre>&lt;code>## GRanges object with 100000 ranges and 0 metadata columns:
## seqnames ranges strand
## &amp;lt;Rle&amp;gt; &amp;lt;IRanges&amp;gt; &amp;lt;Rle&amp;gt;
## SAmvd chr1 29194029-29199925 -
## sPWlf chr1 29738130-29742506 +
## OeOyx chr1 4094438-4099100 -
## iDJdJ chr1 25695446-25695917 -
## QrgNb chr1 7424826-7430143 -
## ... ... ... ...
## BYNer chr5 4638035-4640168 -
## Wqhxl chr5 23896448-23903443 +
## NwlQQ chr5 21284011-21286015 -
## mwQvN chr5 9237160-9244238 +
## obPRS chr5 8099106-8101112 -
## -------
## seqinfo: 5 sequences from mock genome
&lt;/code>&lt;/pre></description></item><item><title>Nicer scatter plots in GGgally ggpairs-ggduo</title><link>https://pascal-martin.netlify.app/post/nicer-scatterplot-in-gggally/</link><pubDate>Wed, 14 Nov 2018 00:00:00 +0000</pubDate><guid>https://pascal-martin.netlify.app/post/nicer-scatterplot-in-gggally/</guid><description>&lt;p>
&lt;a href="http://ggobi.github.io/ggally" target="_blank" rel="noopener">GGally&lt;/a> is an extension of ggplot2. I use it mainly as a replacement/refinement of pairs in base R.&lt;/p>
&lt;p>Here, I want to replace the default scatter plot used to compare 2 continuous variables with something nicer, especially adapted to plotting large number of points.&lt;/p>
&lt;p>Load the library and some RNA-seq data:&lt;/p>
&lt;pre>&lt;code class="language-r">library(GGally)
library(airway)
data(airway)
&lt;/code>&lt;/pre>
&lt;p>The airway dataset contains data for 4 cell lines treated or not with dexamethasone:&lt;/p>
&lt;pre>&lt;code class="language-r">colData(airway)[,1:3]
&lt;/code>&lt;/pre>
&lt;table class="table table-striped table-hover table-responsive" style="width: auto !important; margin-left: auto; margin-right: auto;">
&lt;thead>
&lt;tr>
&lt;th style="text-align:left;"> &lt;/th>
&lt;th style="text-align:left;"> SampleName &lt;/th>
&lt;th style="text-align:left;"> cell &lt;/th>
&lt;th style="text-align:left;"> dex &lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td style="text-align:left;"> SRR1039508 &lt;/td>
&lt;td style="text-align:left;"> GSM1275862 &lt;/td>
&lt;td style="text-align:left;"> N61311 &lt;/td>
&lt;td style="text-align:left;"> untrt &lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align:left;"> SRR1039509 &lt;/td>
&lt;td style="text-align:left;"> GSM1275863 &lt;/td>
&lt;td style="text-align:left;"> N61311 &lt;/td>
&lt;td style="text-align:left;"> trt &lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align:left;"> SRR1039512 &lt;/td>
&lt;td style="text-align:left;"> GSM1275866 &lt;/td>
&lt;td style="text-align:left;"> N052611 &lt;/td>
&lt;td style="text-align:left;"> untrt &lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align:left;"> SRR1039513 &lt;/td>
&lt;td style="text-align:left;"> GSM1275867 &lt;/td>
&lt;td style="text-align:left;"> N052611 &lt;/td>
&lt;td style="text-align:left;"> trt &lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align:left;"> SRR1039516 &lt;/td>
&lt;td style="text-align:left;"> GSM1275870 &lt;/td>
&lt;td style="text-align:left;"> N080611 &lt;/td>
&lt;td style="text-align:left;"> untrt &lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align:left;"> SRR1039517 &lt;/td>
&lt;td style="text-align:left;"> GSM1275871 &lt;/td>
&lt;td style="text-align:left;"> N080611 &lt;/td>
&lt;td style="text-align:left;"> trt &lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align:left;"> SRR1039520 &lt;/td>
&lt;td style="text-align:left;"> GSM1275874 &lt;/td>
&lt;td style="text-align:left;"> N061011 &lt;/td>
&lt;td style="text-align:left;"> untrt &lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align:left;"> SRR1039521 &lt;/td>
&lt;td style="text-align:left;"> GSM1275875 &lt;/td>
&lt;td style="text-align:left;"> N061011 &lt;/td>
&lt;td style="text-align:left;"> trt &lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>Let&amp;rsquo;s keep a fraction of the data for simplicity&lt;/p>
&lt;pre>&lt;code class="language-r">df &amp;lt;- as.data.frame(assays(airway)$counts[,1:4]) #first 4 columns
df &amp;lt;- df[rowSums(df)&amp;gt;4,] #keep genes with some counts
set.seed(123)
df &amp;lt;- df[sample.int(nrow(df),1e3),] #random 1K genes
&lt;/code>&lt;/pre>
&lt;p>default behavior of &lt;code>GGally::ggpair&lt;/code>:&lt;/p>
&lt;pre>&lt;code class="language-r">GGally::ggpairs(log2(df+1))
&lt;/code>&lt;/pre>
&lt;p>&lt;img src="https://pascal-martin.netlify.app/post/2018-11-14-nicer-scatterplot-in-gggally_files/figure-html/unnamed-chunk-6-1.png" width="672" />&lt;/p>
&lt;p>Here is a better function to make the scatterplots in the lower triangle. It is largely based on
&lt;a href="https://drsimonj.svbtle.com/pretty-scatter-plots-with-ggplot2" target="_blank" rel="noopener">this blog post&lt;/a> and implements:&lt;/p>
&lt;ul>
&lt;li>
&lt;a href="https://cran.r-project.org/web/packages/viridis/vignettes/intro-to-viridis.html" target="_blank" rel="noopener">viridis&lt;/a> coloring of points based on expression level (practically based on effect size captured by the first principal component). I added some code to get consistent coloring even if orientation of the first PC differs between pairs of columns.&lt;/li>
&lt;li>&lt;code>alpha&lt;/code> based on inverse of 2D density, i.e. low alpha when there are lots of points and higher when points are more scattered&lt;/li>
&lt;/ul>
&lt;p>Also, the use of &lt;code>GGally:eval_data_col&lt;/code> is described
&lt;a href="https://github.com/ggobi/ggally/issues/139#issuecomment-393201720" target="_blank" rel="noopener">here&lt;/a>:&lt;/p>
&lt;pre>&lt;code class="language-r">GGscatterPlot &amp;lt;- function(data, mapping, ...,
method = &amp;quot;spearman&amp;quot;) {
#Get correlation coefficient
x &amp;lt;- GGally::eval_data_col(data, mapping$x)
y &amp;lt;- GGally::eval_data_col(data, mapping$y)
cor &amp;lt;- cor(x, y, method = method)
#Assemble data frame
df &amp;lt;- data.frame(x = x, y = y)
# PCA
nonNull &amp;lt;- x!=0 &amp;amp; y!=0
dfpc &amp;lt;- prcomp(~x+y, df[nonNull,])
df$cols &amp;lt;- predict(dfpc, df)[,1]
# Define the direction of color range based on PC1 orientation:
dfsum &amp;lt;- x+y
colDirection &amp;lt;- ifelse(dfsum[which.max(df$cols)] &amp;lt;
dfsum[which.min(df$cols)],
1,
-1)
#Get 2D density for alpha
dens2D &amp;lt;- MASS::kde2d(df$x, df$y)
df$density &amp;lt;- fields::interp.surface(dens2D ,
df[,c(&amp;quot;x&amp;quot;, &amp;quot;y&amp;quot;)])
if (any(df$density==0)) {
mini2D = min(df$density[df$density!=0]) #smallest non zero value
df$density[df$density==0] &amp;lt;- mini2D
}
#Prepare plot
pp &amp;lt;- ggplot(df, aes(x=x, y=y, color = cols, alpha = 1/density)) +
ggplot2::geom_point(shape=16, show.legend = FALSE) +
ggplot2::scale_color_viridis_c(direction = colDirection) +
# scale_color_gradient(low = &amp;quot;#0091ff&amp;quot;, high = &amp;quot;#f0650e&amp;quot;) +
ggplot2::scale_alpha(range = c(.05, .6)) +
ggplot2::geom_abline(intercept = 0, slope = 1, col=&amp;quot;darkred&amp;quot;) +
ggplot2::geom_label(
data = data.frame(
xlabel = min(x, na.rm = TRUE),
ylabel = max(y, na.rm = TRUE),
lab = round(cor, digits = 3)),
mapping = ggplot2::aes(x = xlabel,
y = ylabel,
label = lab),
hjust = 0, vjust = 1,
size = 3, fontface = &amp;quot;bold&amp;quot;,
inherit.aes = FALSE # do not inherit anything from the ...
) +
theme_minimal()
return(pp)
}
&lt;/code>&lt;/pre>
&lt;p>Now use in ggpairs (adjust correlation method to be consistent with defaults in GGscatterPlot):&lt;/p>
&lt;pre>&lt;code class="language-r">GGally::ggpairs(log2(df+1),
1:4,
lower = list(continuous = GGscatterPlot),
upper = list(continuous = wrap(&amp;quot;cor&amp;quot;, method= &amp;quot;spearman&amp;quot;)))
&lt;/code>&lt;/pre>
&lt;p>&lt;img src="https://pascal-martin.netlify.app/post/2018-11-14-nicer-scatterplot-in-gggally_files/figure-html/unnamed-chunk-8-1.png" width="672" />&lt;/p>
&lt;p>Now with Pearson correlation coefficient (and removing the correlation coefficient in the upper triangle since we already have them in the lower triangle):&lt;/p>
&lt;pre>&lt;code class="language-r">GGally::ggpairs(log2(df+1),
1:4,
lower = list(continuous = wrap(GGscatterPlot, method=&amp;quot;pearson&amp;quot;)),
upper = &amp;quot;blank&amp;quot;) +
theme_minimal() +
theme(panel.grid.minor = element_blank())
&lt;/code>&lt;/pre>
&lt;p>&lt;img src="https://pascal-martin.netlify.app/post/2018-11-14-nicer-scatterplot-in-gggally_files/figure-html/unnamed-chunk-9-1.png" width="672" />&lt;/p>
&lt;p>We can use the upper triangle to plot other info since the scatter plots include the correlation coefficient.&lt;br>
I illustrate it here with the correlation coefficient for genes with &amp;gt;15 exons vs those with &amp;lt;15 exons:&lt;/p>
&lt;pre>&lt;code class="language-r">exonNumber &amp;lt;- elementNROWS(rowRanges(airway[rownames(df),]))
df$MoreThan15Exons &amp;lt;- ifelse(exonNumber&amp;gt;15,
&amp;quot;&amp;gt;15ex&amp;quot;, &amp;quot;&amp;lt;15ex&amp;quot;)
df[,1:4] &amp;lt;- log2(df[,1:4]+1)
GGally::ggpairs(df,
1:4,
lower = list(continuous = wrap(GGscatterPlot, method=&amp;quot;pearson&amp;quot;)),
upper = list(continuous = wrap(ggally_cor, alignPercent = 0.8),
mapping = ggplot2::aes(color = MoreThan15Exons))) +
theme_minimal() +
theme(panel.grid.minor = element_blank())
&lt;/code>&lt;/pre>
&lt;p>&lt;img src="https://pascal-martin.netlify.app/post/2018-11-14-nicer-scatterplot-in-gggally_files/figure-html/unnamed-chunk-10-1.png" width="672" />&lt;/p>
&lt;p>The &lt;code>GGscatterPlot&lt;/code> function can also be used with &lt;code>GGally::ggduo&lt;/code> to study the link between 2 sets of columns/samples. Here an example comparing control vs DEX samples:&lt;/p>
&lt;pre>&lt;code class="language-r">GGally::ggduo(df,
c(1,3),
c(2,4),
types = list(continuous = GGscatterPlot)) +
theme_minimal() +
theme(panel.grid.minor = element_blank())
&lt;/code>&lt;/pre>
&lt;p>&lt;img src="https://pascal-martin.netlify.app/post/2018-11-14-nicer-scatterplot-in-gggally_files/figure-html/unnamed-chunk-11-1.png" width="672" />&lt;/p></description></item></channel></rss>