Having recently constructed a lot of phylogenetic trees with the module TreeConstruction from Phylo package from Biopython, I've been asked to replace the branch tip labels by the corresponding sequence logos (which I have in the same folder). I thought that it would be more efficient to make a code to generate the logo-trees automatically, as I would have to make a lot of them.
The first idea that I came up with was to see whether the functions used to build the tree had an argument to replace the branch tip labels or to remove them, which I couldn't find. Therefore, I removed the branch tip labels by setting their font size to 0: (following is the code to build the tree)
# Modules to build the tree
from Bio.Phylo.TreeConstruction import DistanceCalculator, DistanceTreeConstructor
from Bio.Phylo import draw
from Bio import Phylo, AlignIO
import subprocess
import matplotlib
import matplotlib.pyplot as plt
alignment = AlignIO.read('MotifSeqAligned.fasta', 'fasta') # reading the alignment file
calculator = DistanceCalculator('ident')
dm = calculator.get_distance(alignment) # distance matrix
constructor = DistanceTreeConstructor()
tree = constructor.nj(dm) # build with neighbour joining algorithm a tree from dm
Phylo.write(tree, 'TreeToCutOff.nwk', 'newick')
plt.rc('font', size=0) # controls default text sizes #HERE IS THE SETTING FOR THAT ALLOWS ME TO HIDE THE BRANCH TIP LABELS
plt.rc('axes', titlesize=14) # fontsize of the axes title
plt.rc('xtick', labelsize=10) # fontsize of the tick labels
plt.rc('ytick', labelsize=10) # fontsize of the tick labels
plt.rc('figure', titlesize=18) # fontsize of the figure title
draw(tree, do_show=False)
plt.savefig("TreeToCutOff.svg", format='svg', dpi=1200)
From this code I could get the tree:
Since I don't know how to get the y coordinates of the branches to add the logos one by one, I built a column of logos with matplotlib, that I intended then to paste on the tree in python. The code to build the column of logos is the following:
#Extract filename from newick
newickFile = open("TreeToCutOff.nwk", 'r').read()
orderedLogos = ["{}.eps".format(i) for i in re.split('(\W)', newickFile) if "Profile" in i]
#Initialize the figure
fig = plt.figure()
#Add each image one after the other in the right order
for i, files in enumerate(orderedLogos):
img1 = mpimg.imread(files)
ax1 = fig.add_subplot(len(orderedLogos), 1, 1+i)
ax1.imshow(img1)
ax1.set_xticks([])
ax1.set_yticks([])
# plt.show()
plt.savefig("RowsOfLogos.svg", format='svg', dpi=1200)
plt.clf()
plt.cla()
Having my tree and the column of logos in .svg or .png, I couldn't find any way to stack them properly. My first idea was to use the library svgutils which seemed to be easy to handle, with the following code: (taken from svgutils tutorials)
import svgutils.transform as sg
# Assemble
#create new SVG figure
fig = sg.SVGFigure("14cm", "14cm")
# load figures
fig1 = sg.fromfile('TreeToCutOff.svg')
fig2 = sg.fromfile('RowsOfLogos.svg')
# get the plot objects
plot1 = fig1.getroot()
plot2 = fig2.getroot()
plot2.moveto(280, 100, scale=0.05)
# append plots and labels to figure
fig.append([plot1, plot2])
But the issue with the output was that the background of the column of logos was white and thus, I was pasting a huge white image with a thin column of logos on the tree. And I couldn't find a way to crop the column of logos with svgutils. I tried the module Image from PIL package to build a tree of logos from .png files but couldn't see the tree used as background after pasting the column of logos.
There may be a way to do what I'm aiming for with matplotlib (which would be to stack 2 files .png, and place the logos all the time at the same distance), but I couldn't work it out.
Does anyone know what the best solution is to make a tree of logos (as in the following image which I could only build manually with inkscape) with python libraries, allowing to automate the process without having to adapt the code depending on the number of branches?
Following is a subset of "MotifSeqAligned.fasta" containing the aligned sequences used to build the trees:
>ProfileCluster0.meme
---SSNDTTTCCAGGAAD-
>ProfileCluster1.meme
YBNRD---TTCYYGGAAT-
>ProfileCluster10.meme
---VDKDWTTCTYGGAAT-
With the 3 corresponding logos:
The full "MotifSeqAligned.fasta" and all the logos.eps (as I used them instead of .png which is the format asked by the forum) can be found here.