Circos plot

Los Circos plot son representaciones circulares originalmente concebidas para representar información genómica (aunque se pueden representar otras cosas). La estructura general puede verse en el siguiente gráfico.

En la parte más externa del gráfico está representado en forma de ideograma la estructura cromosómica del genoma. En las partes más internas se representa diferentes tipos de información (texto, puntos, histogramas…) que está mapeada sobre el genoma, es decir, es información que está localizada “espacialmente” en el mismo usando coordenadas genómicas. A cada una de estas representaciones las llamamos tracks. Por último, en la región más interna se pueden representar relaciones entre diferentes coordenadas genómicas mediante links.

En R hay diferentes paquetes para hacer estas representaciones. La extensión de ggplot2, ggbio es quizás el más potente, pero también el más complejo. En esta introducción veremos RCircos, que es más sencillo.

RCircos

En primer lugar instalamos y cargamos el paquete RCircos

require(RCircos)
## Loading required package: RCircos

El propio paquete tiene una vignette en la cual nos hemos basado para hacer este tutorial.

Configuración del RCircos

Un gráfico Circos empiezan con un ideograma del mapa cromosómico de la especie en cuestión: RCircos viene con ideogramas cromosómicos para tres especies: humano, ratón y rata. Pueden cargarse usando la función de R data(). Carguemos y veamos el de humano:

data(UCSC.HG19.Human.CytoBandIdeogram)
head(UCSC.HG19.Human.CytoBandIdeogram)
##   Chromosome ChromStart ChromEnd   Band  Stain
## 1       chr1          0  2300000 p36.33   gneg
## 2       chr1    2300000  5400000 p36.32 gpos25
## 3       chr1    5400000  7200000 p36.31   gneg
## 4       chr1    7200000  9200000 p36.23 gpos25
## 5       chr1    9200000 12700000 p36.22   gneg
## 6       chr1   12700000 16200000 p36.21 gpos50
str(UCSC.HG19.Human.CytoBandIdeogram)
## 'data.frame':    862 obs. of  5 variables:
##  $ Chromosome: Factor w/ 24 levels "chr1","chr10",..: 1 1 1 1 1 1 1 1 1 1 ...
##  $ ChromStart: int  0 2300000 5400000 7200000 9200000 12700000 16200000 20400000 23900000 28000000 ...
##  $ ChromEnd  : int  2300000 5400000 7200000 9200000 12700000 16200000 20400000 23900000 28000000 30200000 ...
##  $ Band      : Factor w/ 259 levels "p11","p11.1",..: 97 96 95 94 93 92 91 90 89 88 ...
##  $ Stain     : Factor w/ 8 levels "acen","gneg",..: 2 4 2 4 2 5 2 4 2 4 ...

Vemos que el objeto es simplemente un data.frame que contiene la información citogenética a representar.

Los de ratón y rata son, respectivamente, UCSC.Mouse.GRCm38.CytoBandIdeogram y UCSC.Baylor.3.4.Rat.cytoBandIdeogram.

Una vez cargado el ideograma, hay que inicializar los componentes esenciales de RCircos

chr.exclude <- NULL
cyto.info <- UCSC.HG19.Human.CytoBandIdeogram
tracks.inside <- 10
tracks.outside <- 0

RCircos.Set.Core.Components(cyto.info, chr.exclude,
                              tracks.inside, tracks.outside)

Los argumentos son bastante autoexplicativos. En chr.exclude debemos incluir aquellos cromosomas que NO queremos que aparezcan en la representación (el x "chrX" y el Y "chrY" suelen ser los candidatos habituales a excluir)

El ideograma cromosómico a utilizar se explicita en cyto.info mientras que tracks.inside y tracks.outside es el número de tracks a utilizar en el interior y el exterior del ideograma, respectivamente.

Representar el ideograma

Una vez establecidos los componentes esenciales de RCircos podemos hacer una primera representación del ideograma. Aquí es importante tener en cuenta que RCircos no tiene control de los devices gráficos de R. Es decir, debemos trabajar con él dentro del device. Si no especificamos uno, utilizará la salida gŕafica estándar por pantalla. Ahora bien, los Circos plot pueden ser bastante pesados y eso puede dar problemas con Rstudio. Si queremos que la salida sea a un fichero pdf, por ejemplo, habría que abrir dicho device previamente con pdf() y cerrarlo al final con dev.off()

RCircos.Set.Plot.Area()

RCircos.Chromosome.Ideogram.Plot()

Con esto representamos únicamente el ideograma cromosómico. El primer comando prepara (“limpia”, por así decirlo) el área a representar. Siempre que queramos empezar un RCircos de nuevo hay que utilizarlo.

Representemos el ideograma excluyendo los cromosomas X e Y.

chr.exclude <- c("chrX", "chrY")
RCircos.Set.Core.Components(cyto.info, chr.exclude,
                            tracks.inside, tracks.outside)

RCircos.Set.Plot.Area()

RCircos.Chromosome.Ideogram.Plot()

Añadir los tracks

Una vez que ya hemos representado el ideograma, vamos añadiendo tarcks. En nuestro caso, en el interior ya que así lo hemos especificado inicialmente. Existen diferentes tipos de tracks gráficos que pueden añadirse al gráfico:

– heatmap – histogram – lines – scatterplot – tiles

Además se pueden representar enlaces entre regiones o posiciones cromosómicas y también conectores y texto para el nombre de los genes.

Para introducir cada tipo de track se utiliza una función concreta de la forma RCircos.TIPO.Plot. Además, cada fucnión requiere que los datos a representar estén en un data.frame añadidos a su posición genómica.

Por ejemplo, veamos en primer lugar como añadir los nombres de los genes en el Circos plot. Para ello, lo primero es cargar los datos de los nombres de los genes:

data(RCircos.Gene.Label.Data)

head(RCircos.Gene.Label.Data)
##   Chromosome chromStart chromEnd   Gene
## 1       chr1    8921418  8934967   ENO1
## 2       chr1   17345375 17380514   SDHB
## 3       chr1   27022894 27107247 ARID1A
## 4       chr1   41976121 42501596 HIVEP3
## 5       chr1   43803519 43818443    MPL
## 6       chr1   45794977 45805926  MUTYH

Una vez cargados los datos representamos el primer track, en este caso los conectores de las posiciones genómicas a los textos.

chr.exclude <- NULL

RCircos.Set.Core.Components(cyto.info, chr.exclude,
                            tracks.inside, tracks.outside)

RCircos.Set.Plot.Area()

RCircos.Chromosome.Ideogram.Plot()


side <- "in"  # En que lado del ideograma estará: "in" or "out"

track.num <- 1  # La posición del track 

RCircos.Gene.Connector.Plot(RCircos.Gene.Label.Data,
                              track.num, side)

La sintaxis del comando es, de nuevo, muy intuitiva. La función RCircos.Gene.Connector.Plot require los datos (RCircos.Gene.Label.Data), la posición del track en cuestión y si va dentro (“in”) o fuera (“out”) del ideograma. A continuación, usando la función RCircos.Gene.Name.Plot introducimos los nombres de los genes, a esta función hay que pasarle un argumento adicional especificando en qué columna del data.frame están los datos (en este caso los nombres de los genes) a representar.

OJO: Cada vez que se añade un track no es necesario reiniciar todo el plot como aparece en el código de abajo. Esto sólo es necesario para que R Markdown pueda representar cada uno de los plots. En el script con el código limpio adjunto a este tutorial veréis que los tracks se añaden secuencialmente.

 
  RCircos.Set.Plot.Area()

  RCircos.Chromosome.Ideogram.Plot()
  
  side <- "in"  # En que lado del ideograma estará: "in" or "out"
  
  track.num <- 1  # La posición del track 
  
  RCircos.Gene.Connector.Plot(RCircos.Gene.Label.Data,
                              track.num, side)
  track.num <- 2

  name.col <- 4  #indicamos la columna en la que está el nombre

  RCircos.Gene.Name.Plot(RCircos.Gene.Label.Data,
                          name.col,track.num, side)

A continuación incluiremos un par de tracks gráficos. Por ejemplo, un heatmap de la expresión en la línea celular A498. Podemos encontrarla en el dataset RCircos.Heatmap.Data.

data(RCircos.Heatmap.Data)

head(RCircos.Heatmap.Data)
##   Chromosome chromStart chromEnd GeneName  X786.O     A498 A549.ATCC
## 1       chr1     934341   935552     HES4 6.75781  7.38773   6.47890
## 2       chr1     948846   949919    ISG15 7.56297 10.49590   5.89893
## 3       chr1    1138887  1142089 TNFRSF18 4.69775  4.55593   4.38970
## 4       chr1    1270657  1284492     DVL1 7.76886  7.52194   6.87125
## 5       chr1    1288070  1293915    MXRA8 4.49805  4.72032   4.62207
## 6       chr1    1592938  1624243 SLC35E2B 8.73104  8.10229   8.36599
##      ACHN   BT.549  CAKI.1
## 1 6.05517  8.85062 7.00307
## 2 7.58095 12.08470 7.81459
## 3 4.50064  4.47525 4.47721
## 4 7.03517  7.65386 7.69733
## 5 4.58575  5.66389 4.93499
## 6 9.04116  9.24175 9.89727

Donde vemos que la expresión de dicha línea está en la columna 6 y así se lo indicaremos a la función RCircos.Heatmap.Plot

 
  RCircos.Set.Plot.Area()

  RCircos.Chromosome.Ideogram.Plot()
  
  side <- "in"  # En que lado del ideograma estará: "in" or "out"
  
  track.num <- 1  # La posición del track 
  
  RCircos.Gene.Connector.Plot(RCircos.Gene.Label.Data,
                              track.num, side)
  track.num <- 2

  name.col <- 4  #indicamos la columna en la que está el nombre

  RCircos.Gene.Name.Plot(RCircos.Gene.Label.Data,
                          name.col,track.num, side)
 
  data.col <- 6   

  track.num <- 3

  RCircos.Heatmap.Plot(RCircos.Heatmap.Data, data.col,
                     track.num, side)

Siguendo este esquema general existen otros tipos de funciones para representar tracks gráficos. En el codigo siguiente se muestra el resto. Con todos ellos formamos un RCircos completo.

  RCircos.Set.Plot.Area()

  RCircos.Chromosome.Ideogram.Plot()
  
  side <- "in"  # En que lado del ideograma estará: "in" or "out"
  
  track.num <- 1  # La posición del track 
  
  RCircos.Gene.Connector.Plot(RCircos.Gene.Label.Data,
                              track.num, side)
  track.num <- 2

  name.col <- 4  #indicamos la columna en la que está el nombre

  RCircos.Gene.Name.Plot(RCircos.Gene.Label.Data,
                          name.col,track.num, side)
 
  data.col <- 6   

  track.num <- 3

  RCircos.Heatmap.Plot(RCircos.Heatmap.Data, data.col,
                     track.num, side)

 data(RCircos.Line.Data)
 
 data.col <- 5
 track.num <- 4
 side <- "in"
 RCircos.Line.Plot(RCircos.Line.Data, data.col,
                     track.num, side)
 
 
 data(RCircos.Scatter.Data)
 data.col <- 5
 track.num <- 5
 side <- "in"
 by.fold <- 1   # los puntos con un valor por encima de by.fold se pintan en rojo 
 RCircos.Scatter.Plot(RCircos.Scatter.Data, data.col,
                      track.num, side, by.fold)
 
 
 data(RCircos.Histogram.Data)
 data.col <- 4
 track.num <- 6
 side <- "in"
 RCircos.Histogram.Plot(RCircos.Histogram.Data,
                          data.col, track.num, side)
 
 
 data(RCircos.Tile.Data)
 track.num <- 7
 side <- "in"
 RCircos.Tile.Plot(RCircos.Tile.Data, track.num, side)

Enlaces

El último tipo de representación de los Circos son los enlaces entre posiciones del genoma. En RCircos estos enlaces pueden ser links si son entre regiones pequeñas o ribbons si son entre regiones más o menos grandes. Veamos los datasets de ejemplo para los links

 data(RCircos.Link.Data)
 
 head(RCircos.Link.Data)
##   Chromosome chromStart  chromEnd Chromosome.1 chromStart.1 chromEnd.1
## 1       chr1    8284703   8285399         chr1      8285752    8286389
## 2       chr1   85980143  85980624         chr7    123161313  123161687
## 3       chr1  118069850 118070319         chr1    118070329  118070689
## 4       chr1  167077258 167077658         chr1    169764630  169764965
## 5       chr1  171671272 171671550         chr1    179790879  179791292
## 6       chr1  174333479 174333875         chr6    101861516  101861840

y para los ribbons

 data(RCircos.Ribbon.Data)
 head(RCircos.Ribbon.Data)
##   chromA chromStartA chromEndA chromB chromStartB chromEndB
## 1   chr1    28000000  84900000  chr18    19000000  56200000
## 2   chr1   214500000 236600000  chr10     3800000  17300000
## 3   chr5    62900000 104500000  chr13    79000000 104800000
## 4   chr8    73900000 139900000  chr17           0  22200000

En ambos casos se va a representar un data.frame en el que en cada línea hay dos regiones genómicas representadas por el cromosoma, la posición en la que empieza y la que acaba. Se ve que la única diferencia entre los datos de los links y los de los ribbons es el tamaño de dichas regiones. Para representarlo se hace lo siguiente.

  RCircos.Set.Plot.Area()

  RCircos.Chromosome.Ideogram.Plot()
  
  side <- "in"  # En que lado del ideograma estará: "in" or "out"
  
  track.num <- 1  # La posición del track 
  
  RCircos.Gene.Connector.Plot(RCircos.Gene.Label.Data,
                              track.num, side)
  track.num <- 2

  name.col <- 4  #indicamos la columna en la que está el nombre

  RCircos.Gene.Name.Plot(RCircos.Gene.Label.Data,
                          name.col,track.num, side)
 
  data.col <- 6   

  track.num <- 3

  RCircos.Heatmap.Plot(RCircos.Heatmap.Data, data.col,
                     track.num, side)

 data(RCircos.Line.Data)
 
 data.col <- 5
 track.num <- 4
 side <- "in"
 RCircos.Line.Plot(RCircos.Line.Data, data.col,
                     track.num, side)
 
 
 data(RCircos.Scatter.Data)
 data.col <- 5
 track.num <- 5
 side <- "in"
 by.fold <- 1   # los puntos con un valor por encima de by.fold se pintan en rojo 
 RCircos.Scatter.Plot(RCircos.Scatter.Data, data.col,
                      track.num, side, by.fold)
 
 
 data(RCircos.Histogram.Data)
 data.col <- 4
 track.num <- 6
 side <- "in"
 RCircos.Histogram.Plot(RCircos.Histogram.Data,
                          data.col, track.num, side)
 
 
 data(RCircos.Tile.Data)
 track.num <- 7
 side <- "in"
 RCircos.Tile.Plot(RCircos.Tile.Data, track.num, side)

 track.num <- 8
 RCircos.Link.Plot(RCircos.Link.Data, track.num, by.chromosome = TRUE)
 
 RCircos.Ribbon.Plot(ribbon.data=RCircos.Ribbon.Data,
                        track.num=9, by.chromosome=FALSE, twist=FALSE)

En la ayuda de ambas funciones puede verse como cambiar algunas de las propiedades de los gráficos como la posibilidad de que haya twist en los ribbons o que los colores sean diferentes en los enlaces intra o extracromosomicos.

Más recursos

Este tutorial es, básicamente, una reorganización de la viñeta del paquete, donde puede encontrarse más información para modificar algunas de las propiedades de los Circos.