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 MockFirmicutes Bacilli Bacillales Staphylococcaceae Staphylococcus Staphylococcus_pasteuri 623Proteobacteria Gammaproteobacteria Pseudomonadales Moraxellaceae Acinetobacter Acinetobacter_baumannii 410Firmicutes Bacilli Bacillales Bacillaceae Bacillus Bacillus_bingmayongensis 385Actinobacteria Actinobacteria_c Actinomycetales Actinomycetaceae Actinomyces Actinomyces_odontolyticus 362Proteobacteria Epsilonproteobacteria Campylobacterales Helicobacteraceae Helicobacter CP002336_s 361Firmicutes Clostridia Clostridiales Clostridiaceae Clostridium Clostridium_puniceum 310Proteobacteria Betaproteobacteria Neisseriales Neisseriaceae Neisseria Neisseria_meningitidis 305Bacteroidetes Bacteroidia Bacteroidales Bacteroidaceae Bacteroides Bacteroides_dorei 250Firmicutes Bacilli Lactobacillales Streptococcaceae Streptococcus Streptococcus_mutans 232Con tablas dinámicas de Excel podemos convertir cada dos columnas (taxón) en combinaciones, p. ej. para phylum class:
Actinobacteria Actinobacteria_c 368Bacteroidetes Bacteroidia 393Deinococcus-Thermus Deinococci 118Firmicutes Bacilli 2006Firmicutes Clostridia 312Firmicutes Erysipelotrichi 2La 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.
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>