<p>To expand on my comment from yesterday. You could do this with the <a href="http://etetoolkit.org" rel="noreferrer">ETE Toolkit</a> (I just copied one logo file rather than converting all 26 to <code>png</code>):</p>

<pre><code>from ete3 import Tree, TreeStyle, faces
def mylayout(node):
    if node.is_leaf():
        logo_face = faces.ImgFace(str.split(node.name, '.')[0] + ".png") # this doesn't seem to work with eps files. You could try other formats
        faces.add_face_to_node(logo_face, node, column=0)
    node.img_style["size"] = 0  # remove blue dots from nodes

t = Tree("tree.nwk", format=3)
ts = TreeStyle()
ts.layout_fn = mylayout
ts.show_leaf_name=False # remove sequence labels
ts.scale =  10000 # rescale branch lengths so they are longer than the width of the logos
t.render("formatted.png", tree_style = ts, h=3000, w=3000) # you may need to fiddle with dimensions and scaling to get the look you want
</code></pre>

<p><a href="https://i.sstatic.net/Yd8z6.png" rel="noreferrer"><img src="https://i.sstatic.net/Yd8z6.png" alt="enter image description here"></a></p>

<p>If you want all of the logos lined up in a column add <code>aligned=True</code> to <code>faces.add_face_to_node</code></p>

CC BY-SA 4.0
2018-05-22T11:11:57.973Z
Thanks! That's exactly what I was looking for! I will try with all my logos and let you know if I have further issues.
Boris Schnider
CC BY-SA 4.0
2018-05-22T09:29:00.973Z
2018-05-22T10:17:08.633Z
2018-05-22T10:17:08.633Z
heathobrien
<p>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.</p>

<p>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)</p>

<pre><code># 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)
</code></pre>

<p>From this code I could get the tree:
<a href="https://i.sstatic.net/eLc0c.png" rel="noreferrer"><img src="https://i.sstatic.net/eLc0c.png" alt="enter image description here"></a></p>

<p>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:</p>

<pre><code>#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()
</code></pre>

<p><a href="https://i.sstatic.net/tamkV.png" rel="noreferrer"><img src="https://i.sstatic.net/tamkV.png" alt="enter image description here"></a></p>

<p>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)</p>

<pre><code>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])
</code></pre>

<p>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.</p>

<p>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.</p>

<p>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?</p>

<p><a href="https://i.sstatic.net/M7p7a.png" rel="noreferrer"><img src="https://i.sstatic.net/M7p7a.png" alt="enter image description here"></a></p>

<p>Following is a subset of "MotifSeqAligned.fasta" containing the aligned sequences used to build the trees:</p>

<pre><code>&gt;ProfileCluster0.meme
---SSNDTTTCCAGGAAD-
&gt;ProfileCluster1.meme
YBNRD---TTCYYGGAAT-
&gt;ProfileCluster10.meme
---VDKDWTTCTYGGAAT-
</code></pre>

<p>With the 3 corresponding logos:
<a href="https://i.sstatic.net/4GChu.png" rel="noreferrer"><img src="https://i.sstatic.net/4GChu.png" alt="enter image description here"></a>
<a href="https://i.sstatic.net/ATI9L.png" rel="noreferrer"><img src="https://i.sstatic.net/ATI9L.png" alt="enter image description here"></a>
<a href="https://i.sstatic.net/TjhTt.png" rel="noreferrer"><img src="https://i.sstatic.net/TjhTt.png" alt="enter image description here"></a></p>

<p>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 <a href="https://github.com/bschnide/Tree-Logos" rel="noreferrer">here</a>.</p>

CC BY-SA 4.0
2018-05-21T13:59:39.887Z
Thank you for putting so much effort into your question! If I could ask for one more thing though, it would be great if you could give us a [minimal, complete and verifiable example](https://stackoverflow.com/help/mcve), code that we can use directly on our system to replicate your issue so we can play with it and see if we can find a solution.
terdon
CC BY-SA 4.0
2018-05-21T14:53:03.673Z
Thank you for the suggestion, I added the inputs at the end of the topic. Note that the logos are .eps files and here I added them as images (.png). The full inputs are on the link at the end of the topic.
Boris Schnider
CC BY-SA 4.0
2018-05-21T15:23:12.257Z
If there's no obvious biopython solution have a look at the [ETE Toolkit](http://etetoolkit.org)
heathobrien
<python><motifs><phylogenetics>
Biopython Phylogenetic Tree replace branch tip labels by sequence logos
# Biopython Phylogenetic Tree replace branch tip labels by sequence logos

(Asked by: username_0 on 2018-05-21)

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.

**Tags:** python, motifs, phylogenetics
> **Comments:**
> **username_1**: Thank you for putting so much effort into your question! If I could ask for one more thing though, it would be great if you could give us a [minimal, complete and verifiable example](https://stackoverflow.com/help/mcve), code that we can use directly on our system to replicate your issue so we can play with it and see if we can find a solution.  
> **username_0**: Thank you for the suggestion, I added the inputs at the end of the topic. Note that the logos are .eps files and here I added them as images (.png). The full inputs are on the link at the end of the topic.  
> **username_2**: If there's no obvious biopython solution have a look at the [ETE Toolkit](http://etetoolkit.org)  

---

## 1 answers

### Answer by username_2 on 2018-05-22. Score: 8 | Accepted answer

To expand on my comment from yesterday. You could do this with the ETE Toolkit (I just copied one logo file rather than converting all 26 to png):
from ete3 import Tree, TreeStyle, faces
def mylayout(node):
    if node.is_leaf():
        logo_face = faces.ImgFace(str.split(node.name, '.')[0] + ".png") # this doesn't seem to work with eps files. You could try other formats
        faces.add_face_to_node(logo_face, node, column=0)
    node.img_style["size"] = 0  # remove blue dots from nodes

t = Tree("tree.nwk", format=3)
ts = TreeStyle()
ts.layout_fn = mylayout
ts.show_leaf_name=False # remove sequence labels
ts.scale =  10000 # rescale branch lengths so they are longer than the width of the logos
t.render("formatted.png", tree_style = ts, h=3000, w=3000) # you may need to fiddle with dimensions and scaling to get the look you want


If you want all of the logos lined up in a column add aligned=True to faces.add_face_to_node

> **Comments:**
> **username_0**: Thanks! That's exactly what I was looking for! I will try with all my logos and let you know if I have further issues.  

---

