Sankey

Los diagramas llamados Sankey o Alluvial son representaciones gráficas de la cantidad de secuencias asignadas a cada nivel taxonómico para una muestra o promedio de muestras, no es apto para representar varias muestras. El paso complicado de estos diagramas es darle a los dato el formato necesario; podemos partir de una tabla de OTUs y con ayuda del excel conseguir el formato adecuado. Uno de los mejores programas para conseguir ya el diagrama es Google Charts, que genera el diagrama en formato html listo para abrirlo en cualquier navegador.

Formato necesario para Google Charts Sankey Plot. Este formato es algo complicado pero básicamente se trata de ordenar la muestra por pares de taxones, p.ej. phylum con clase y cuantas secuencias para esa relación, una vez que se terminaron todas las combinaciones phylum clase, se sigue con clase orden, etc. Ya que es un código html, tiene que tener algunos caracteres que dividan los datos como se explica.

Esto lo podemos hacer relativamente sencillo con la Tablas Dinámicas de Excel y partiendo de una tabla de OTUs, como la que genera nuestro clasificador mg_classifier, llamada OTU_table.tsv

Ejemplo de una tabla de OTUs, cada taxon está dividido por tabuladores y al final está el valor para esa OTU.

Phylum Class Order Family Genus Species Mock
Firmicutes Bacilli Bacillales Staphylococcaceae Staphylococcus Staphylococcus_pasteuri 623
Proteobacteria Gammaproteobacteria Pseudomonadales Moraxellaceae Acinetobacter Acinetobacter_baumannii 410
Firmicutes Bacilli Bacillales Bacillaceae Bacillus Bacillus_bingmayongensis 385
Actinobacteria Actinobacteria_c Actinomycetales Actinomycetaceae Actinomyces Actinomyces_odontolyticus 362
Proteobacteria Epsilonproteobacteria Campylobacterales Helicobacteraceae Helicobacter CP002336_s 361
Firmicutes Clostridia Clostridiales Clostridiaceae Clostridium Clostridium_puniceum 310
Proteobacteria Betaproteobacteria Neisseriales Neisseriaceae Neisseria Neisseria_meningitidis 305
Bacteroidetes Bacteroidia Bacteroidales Bacteroidaceae Bacteroides Bacteroides_dorei 250
Firmicutes Bacilli Lactobacillales Streptococcaceae Streptococcus Streptococcus_mutans 232

Con tablas dinámicas de Excel podemos convertir cada dos columnas (taxón) en combinaciones, p. ej. para phylum class:

Actinobacteria  Actinobacteria_c 368
Bacteroidetes Bacteroidia 393
Deinococcus-Thermus Deinococci 118
Firmicutes Bacilli 2006
Firmicutes Clostridia 312
Firmicutes Erysipelotrichi 2

La tabla dinámica puede configurarse para que se presenten los datos como se muestra a la derecha:

Ahora con una función (en la cuata columna de un archivo excel) podemos poner los caracteres html necesarios, la función es: =CONCATENAR("[ '",A1,"', '",B1,"', ",C1," ],")

Cada par de taxones va en una línea de la siguiente manera: [ 'Taxon_Sup', 'Taxon_Inf', valor ], donde Taxon_Sup es el phylum, por ejemplo, y el Taxon_Inf la clase y el valor, el número se secuencias para esa relación. Los nombre de los taxones van entre comillas sencillas separados por comas. Todo el argumento van entre corchetes [ ] y al final de la línea se termina con otra coma.

Actinobacteria  Actinobacteria_c 368 [ 'Actinobacteria', 'Actinobacteria_c', 368 ],
Bacteroidetes Bacteroidia 393 [ 'Bacteroidetes', 'Bacteroidia', 393 ],
Deinococcus-Thermus Deinococci 118 [ 'Deinococcus-Thermus', 'Deinococci', 118 ],
Firmicutes Bacilli 2006 [ 'Firmicutes', 'Bacilli', 2006 ],
Firmicutes Clostridia 312 [ 'Firmicutes', 'Clostridia', 312 ],
Firmicutes Erysipelotrichi 2 [ 'Firmicutes', 'Erysipelotrichi', 2 ],

Así ya tenemos en la última columna el formato requerido para insertar al código html. Aquí solo está ejemplificado para la relación phylum clase, habría que hacerlo para todas las relaciones inferiores.

Cuando una línea empieza con // implica que es un comentario lo que sigue y por lo tanto no es parte del código, solo nos sirve para saber en dónde van los datos, es opcional. Aquí se presentan solo las primeras 4 a 6 combinaciones para cada par de taxones.

//phylum-class
  [ 'Actinobacteria', 'Actinobacteria_c', 368 ],
  [ 'Bacteroidetes', 'Bacteroidia', 393 ],
  [ 'Deinococcus-Thermus', 'Deinococci', 118 ],  
  [ 'Firmicutes', 'Bacilli', 2006 ],
  [ 'Firmicutes', 'Clostridia', 312 ],
  [ 'Firmicutes', 'Erysipelotrichi', 2 ],
// class-order
  [ 'Alphaproteobacteria', 'Rhizobiales', 3539 ],
  [ 'Alphaproteobacteria', 'Rhodobacterales', 989 ],
  [ 'Alphaproteobacteria', 'Rhodospirillales', 1002 ],
  [ 'Alphaproteobacteria', 'Rickettsiales', 114 ],
//order-family
  [ 'Burkholderiales', 'Ralstonia_f', 146 ],
  [ 'Campylobacterales', 'Helicobacteraceae', 569 ],
  [ 'Campylobacterales', 'Unclassified_Camp', 168 ],
  [ 'Cellvibrionales', 'Cellvibrionaceae', 229 ],
// family-genus
  [ 'AF181991_f', 'M90415_g', 120 ],
  [ 'AJ224942_f', 'GQ259251_g', 112 ],
  [ 'Cellvibrionaceae', 'Umboniibacter', 229 ],
  [ 'Desulfobacteraceae', 'AXXL_g', 164 ],

Una vez teniendo este listado ya en el formato adecuado, habría que insertarlo en el código html para el diagrama Sankey, que se muestra a abajo, éste código se puede copiar y pegar en un archivo y salvarlo mock.html, por ejemplo. Al abrirlo genera un gráfico como el de la izquierda, aquí está con más detalle.

Código Sankey.

El texto en negritas es el código que genera el gráfico y los datos generados anteriormente están sin negritas. Opciones modificables del gráfico están al final. En caso de ser necesario usar otros datos, solo borrar los que están sin negritas y sustituirlos por los nuevos.

<html>
<body>
 <script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>

<div id="sankey_multiple" style="width: 2000px; height: 1200px;"></div>

<script type="text/javascript">
  google.charts.load("current", {packages:["sankey"]});
  google.charts.setOnLoadCallback(drawChart);
  function drawChart() {
  var data = new google.visualization.DataTable();
  data.addColumn('string', 'From');
  data.addColumn('string', 'To');
  data.addColumn('number', 'Weight');
  data.addRows([
 //phylum-class
[ 'Actinobacteria', 'Actinobacteria_c', 368 ],
[ 'Bacteroidetes', 'Bacteroidia', 393 ],
[ 'Deinococcus-Thermus', 'Deinococci', 118 ],
[ 'Firmicutes', 'Bacilli', 2006 ],
[ 'Firmicutes', 'Clostridia', 312 ],
[ 'Firmicutes', 'Erysipelotrichi', 2 ],
[ 'Proteobacteria', 'Alphaproteobacteria', 55 ],
[ 'Proteobacteria', 'Betaproteobacteria', 305 ],
[ 'Proteobacteria', 'Epsilonproteobacteria', 363 ],
[ 'Proteobacteria', 'Gammaproteobacteria', 758 ],
 // class-order
[ 'Actinobacteria_c', 'Actinomycetales', 366 ],
[ 'Actinobacteria_c', 'Propionibacteriales', 2 ],
[ 'Alphaproteobacteria', 'Rhodobacterales', 55 ],
[ 'Bacilli', 'Bacillales', 1176 ],
[ 'Bacilli', 'Lactobacillales', 830 ],
[ 'Bacteroidia', 'Bacteroidales', 393 ],
[ 'Betaproteobacteria', 'Neisseriales', 305 ],
[ 'Clostridia', 'Clostridiales', 312 ],
[ 'Deinococci', 'Deinococcales', 118 ],
[ 'Epsilonproteobacteria', 'Campylobacterales', 363 ],
[ 'Erysipelotrichi', 'Erysipelotrichales', 2 ],
[ 'Gammaproteobacteria', 'Enterobacteriales', 200 ],
[ 'Gammaproteobacteria', 'Pseudomonadales', 558 ],
  //order-family
[ 'Actinomycetales', 'Actinomycetaceae', 366 ],
[ 'Bacillales', 'Bacillaceae', 389 ],
[ 'Bacillales', 'Listeriaceae', 159 ],
[ 'Bacillales', 'Staphylococcaceae', 628 ],
[ 'Bacteroidales', 'Bacteroidaceae', 274 ],
[ 'Bacteroidales', 'Porphyromonadaceae', 109 ],
[ 'Bacteroidales', 'S24-7_f', 10 ],
[ 'Campylobacterales', 'Helicobacteraceae', 363 ],
[ 'Clostridiales', 'Clostridiaceae', 310 ],
[ 'Clostridiales', 'Lachnospiraceae', 2 ],
[ 'Deinococcales', 'Deinococcaceae', 118 ],
[ 'Enterobacteriales', 'Enterobacteriaceae', 200 ],
[ 'Erysipelotrichales', 'Erysipelotrichaceae', 2 ],
[ 'Lactobacillales', 'Enterococcaceae', 197 ],
[ 'Lactobacillales', 'Lactobacillaceae', 141 ],
[ 'Lactobacillales', 'Streptococcaceae', 492 ],
[ 'Neisseriales', 'Neisseriaceae', 305 ],
[ 'Propionibacteriales', 'Propionibacteriaceae', 2 ],
[ 'Pseudomonadales', 'Moraxellaceae', 412 ],
[ 'Pseudomonadales', 'Pseudomonadaceae', 146 ],
[ 'Rhodobacterales', 'Rhodobacteraceae', 55 ],
  // family-genus
[ 'Actinomycetaceae', 'Actinomyces', 366 ],
[ 'Bacillaceae', 'Bacillus', 387 ],
[ 'Bacillaceae', 'Bacillus_g6', 2 ],
[ 'Bacteroidaceae', 'Bacteroides', 274 ],
[ 'Clostridiaceae', 'Clostridium', 310 ],
[ 'Deinococcaceae', 'Deinococcus', 118 ],
[ 'Enterobacteriaceae', 'Salmonella', 200 ],
[ 'Enterococcaceae', 'Enterococcus', 197 ],
[ 'Erysipelotrichaceae', 'Turicibacter', 2 ],
[ 'Helicobacteraceae', 'Helicobacter', 363 ],
[ 'Lachnospiraceae', 'Eubacterium_g17', 2 ],
[ 'Lactobacillaceae', 'Lactobacillus', 141 ],
[ 'Listeriaceae', 'Listeria', 159 ],
[ 'Moraxellaceae', 'Acinetobacter', 412 ],
[ 'Neisseriaceae', 'Neisseria', 305 ],
[ 'Porphyromonadaceae', 'Porphyromonas', 109 ],
[ 'Propionibacteriaceae', 'Propionibacterium', 2 ],
[ 'Pseudomonadaceae', 'Pseudomonas', 146 ],
[ 'Rhodobacteraceae', 'Rhodobacter', 55 ],
[ 'S24-7_f', 'DQ815871_g', 2 ],
[ 'S24-7_f', 'EF406806_g', 6 ],
[ 'S24-7_f', 'HM124247_g', 2 ],
[ 'Staphylococcaceae', 'Staphylococcus', 628 ],
[ 'Streptococcaceae', 'Streptococcus', 492 ],
  ]);

 // Set chart options
  var options = {
   width: 1300,
   hight: 1000,
   sankey: {
     node: { 
      label: { fontName: 'Helvetica', fontSize: 13, color: '#4a4848', italic: true},
      width: 10,
      nodePadding: 10,
      interactivity: true
      },
     link: {
      colorMode: 'source',
      color : {stroke: '#c9c7c7', strokeWidth: 1, fillOpacity: 0.8 },
      },
     interations: 128,
     },
  };
 // Instantiate and draw our chart, passing in some options.
  var chart = new google.visualization.Sankey(document.getElementById('sankey_multiple'));
  chart.draw(data, options);
 }
</script>
</body>
</html>