Skip to content

Commit

Permalink
huge update on look and backend of plots; easy make cmd for figure ge…
Browse files Browse the repository at this point in the history
…neration added; scripts slightly modified; figures updated
  • Loading branch information
Felix Simkovic committed Feb 8, 2017
1 parent c33b01d commit 0c35fcc
Show file tree
Hide file tree
Showing 11 changed files with 217 additions and 56 deletions.
106 changes: 69 additions & 37 deletions conkit/plot/ContactMapPlot.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
import numpy

from conkit import constants
from conkit.core import ContactMap
from conkit.plot._Figure import Figure


Expand All @@ -25,59 +24,92 @@ def __init__(self, hierarchy, other=None, reference=None, altloc=False, use_conf
Parameters
----------
hierarchy : :obj:`conkit.core.ContactMap`
A ConKit :obj:`conkit.core.ContactMap`
The default contact map hierarchy
other : :obj:`conkit.core.ContactMap`, optional
A ConKit :obj:`conkit.core.ContactMap`
The second contact map hierarchy
reference : :obj:`conkit.core.ContactMap`, optional
A ConKit :obj:`conkit.core.ContactMap` [this map refers to the reference contacts]
The reference contact map hierarchy
altloc : bool, optional
Use the res_altloc positions [default: False]
use_conf : bool, optional
The marker size will correspond to the raw score [default: False]
**kwargs
General :obj:`conkit.plot._Figure.Figure` keyword arguments
Raises
------
RuntimeError
The hierarchy is not a :obj:`conkit.core.SequenceFile` object
"""
super(ContactMapFigure, self).__init__(**kwargs)

if not isinstance(hierarchy, ContactMap):
raise RuntimeError("Provided hierarchy is not a ContactMap")
elif other and not isinstance(other, ContactMap):
raise RuntimeError("Provided other hierarchy is not a ContactMap")
elif reference and not isinstance(reference, ContactMap):
raise RuntimeError("Provided reference hierarchy is not a ContactMap")
self._hierarchy = None
self._other = None
self._reference = None

self.altloc = altloc
self.use_conf = use_conf

self.hierarchy = hierarchy
self.other = other
self.reference = reference

self._draw()

@property
def hierarchy(self):
"""The default contact map hierarchy"""
return self._hierarchy

@hierarchy.setter
def hierarchy(self, hierarchy):
"""Define the default contact map hierarchy"""
if hierarchy:
Figure._check_hierarchy(hierarchy, "ContactMap")
self._hierarchy = hierarchy
self._other = other
self._reference = reference
self._altloc = altloc
self._use_conf = use_conf

@property
def other(self):
"""The second contact map hierarchy"""
return self._other

@other.setter
def other(self, hierarchy):
"""Define the default contact map hierarchy"""
if hierarchy:
Figure._check_hierarchy(hierarchy, "ContactMap")
self._other = hierarchy

@property
def reference(self):
"""The reference contact map hierarchy"""
return self._reference

@reference.setter
def reference(self, hierarchy):
"""Define the reference contact map hierarchy"""
if hierarchy:
Figure._check_hierarchy(hierarchy, "ContactMap")
self._reference = hierarchy

def redraw(self):
"""Re-draw the plot with updated parameters"""
self._draw()

def draw(self):
def _draw(self):
"""Draw the actual plot"""

fig, ax = matplotlib.pyplot.subplots(dpi=self.dpi)

# Plot the other_ref contacts
if self._reference:
if self._altloc:
if self.altloc:
reference_data = numpy.asarray([(c.res1_altseq, c.res2_altseq)
for c in self._reference if c.is_true_positive])
else:
reference_data = numpy.asarray([(c.res1_seq, c.res2_seq)
for c in self._reference if c.is_true_positive])
reference_colors = [constants.RFCOLOR for _ in range(len(reference_data))]
ax.scatter(reference_data.T[0], reference_data.T[1], color=reference_colors,
marker='.', edgecolor='none', linewidths=0.0)
s=10, marker='o', edgecolor='none', linewidths=0.0)
ax.scatter(reference_data.T[1], reference_data.T[0], color=reference_colors,
marker='.', edgecolor='none', linewidths=0.0)
s=10, marker='o', edgecolor='none', linewidths=0.0)

# Plot the self contacts
self_data = numpy.asarray([(c.res1_seq, c.res2_seq, c.raw_score) for c in self._hierarchy])
Expand All @@ -86,14 +118,14 @@ def draw(self):
else constants.FPCOLOR if contact.is_false_positive
else constants.NTCOLOR for contact in self._hierarchy
]
if self._use_conf:
# TODO: Find a better scaling algorithm
self_sizes = (self_data.T[2] - self_data.T[2].min()) / (self_data.T[2].max() - self_data.T[2].min()) * 500
if self.use_conf:
self_sizes = (self_data.T[2] - self_data.T[2].min()) / (self_data.T[2].max() - self_data.T[2].min())
self_sizes = self_sizes * 20 + 10
else:
self_sizes = None
self_sizes = [10] * len(self_data.T[2])

# This is the bottom triangle
ax.scatter(self_data.T[1], self_data.T[0], color=self_colors, marker='.',
ax.scatter(self_data.T[1], self_data.T[0], color=self_colors, marker='o',
s=self_sizes, edgecolor='none', linewidths=0.0)

# Plot the other contacts
Expand All @@ -104,17 +136,17 @@ def draw(self):
else constants.FPCOLOR if contact.is_false_positive
else constants.NTCOLOR for contact in self._other
]
if self._use_conf:
# TODO: Find a better scaling algorithm
other_sizes = (other_data.T[2] - other_data.T[2].min()) / (other_data.T[2].max() - other_data.T[2].min()) * 500
if self.use_conf:
other_sizes = (other_data.T[2] - other_data.T[2].min()) / (other_data.T[2].max() - other_data.T[2].min())
other_sizes = other_sizes * 20 + 10
else:
other_sizes = None
other_sizes = [10] * len(other_data.T[2])
# This is the upper triangle
ax.scatter(other_data.T[0], other_data.T[1], color=other_colors, marker='.',
ax.scatter(other_data.T[0], other_data.T[1], color=other_colors, marker='o',
s=other_sizes, edgecolor='none', linewidths=0.0)
else:
# This is the upper triangle
ax.scatter(self_data.T[0], self_data.T[1], color=self_colors, marker='.',
ax.scatter(self_data.T[0], self_data.T[1], color=self_colors, marker='o',
s=self_sizes, edgecolor='none', linewidths=0.0)

# Allow dynamic x and y limits
Expand All @@ -140,11 +172,11 @@ def draw(self):
# Create a custom legend
if self._reference:
tp_artist = matplotlib.pyplot.Line2D((0, 1), (0, 0), color=constants.TPCOLOR,
marker='o', linestyle='', label='True positive')
marker='o', linestyle='', label='Match')
fp_artist = matplotlib.pyplot.Line2D((0, 1), (0, 0), color=constants.FPCOLOR,
marker='o', linestyle='', label='False positive')
marker='o', linestyle='', label='Mismatch')
rf_artist = matplotlib.pyplot.Line2D((0, 1), (0, 0), color=constants.RFCOLOR,
marker='o', linestyle='', label='Reference')
marker='o', linestyle='', label='Structural')
artists = [tp_artist, fp_artist, rf_artist]
else:
nt_artist = matplotlib.pyplot.Line2D((0, 1), (0, 0), color=constants.NTCOLOR,
Expand Down
41 changes: 26 additions & 15 deletions conkit/plot/SequenceCoveragePlot.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
import matplotlib.pyplot
import numpy

from conkit.core import SequenceFile
from conkit.plot._Figure import Figure


Expand All @@ -27,24 +26,35 @@ def __init__(self, hierarchy, **kwargs):
**kwargs
General :obj:`conkit.plot._Figure.Figure` keyword arguments
Raises
------
RuntimeError
The hierarchy is not an alignment
RuntimeError
The hierarchy is not a :obj:`conkit.core.SequenceFile` object
"""
super(SequenceCoverageFigure, self).__init__(**kwargs)
self._hierarchy = hierarchy
self._draw()

if not isinstance(hierarchy, SequenceFile):
raise RuntimeError("Provided hierarchy is not a SequenceFile")
@property
def hierarchy(self):
"""A ConKit :obj:`conkit.core.SequenceFile`"""
return self._hierarchy

if not hierarchy.is_alignment:
raise RuntimeError("Provided hierarchy does not show characteristics of an alignment")
@hierarchy.setter
def hierarchy(self, hierarchy):
"""Define the ConKit :obj:`conkit.core.SequenceFile`
Raises
------
RuntimeError
The hierarchy is not an alignment
"""
if hierarchy:
Figure._check_hierarchy(hierarchy, "SequenceFile")
if not hierarchy.is_alignment:
raise RuntimeError("Provided hierarchy does not show characteristics of an alignment")
self._hierarchy = hierarchy

def redraw(self):
"""Re-draw the plot with updated parameters"""
self._draw()

def _draw(self):
Expand All @@ -54,15 +64,16 @@ def _draw(self):
aa_frequencies = numpy.asarray(self._hierarchy.calculate_freq()) * self._hierarchy.top_sequence.seq_len

fig, ax = matplotlib.pyplot.subplots(dpi=self.dpi)
ax.plot(residues, aa_frequencies, color='#000000', marker='.', linestyle='-',
label='Amino acid count')
ax.plot(residues, aa_frequencies, color='#000000', marker='o', linestyle='-',
markersize=5, label='Amino acid count')

ax.axhline(self._hierarchy.top_sequence.seq_len * 0.3, color='r', label='30% Coverage')
ax.axhline(self._hierarchy.top_sequence.seq_len * 0.6, color='g', label='60% Coverage')

# Prettify the plot
ax.set_xticks(residues)
ax.set_xticklabels(residues)
xticks = numpy.arange(1, self._hierarchy.top_sequence.seq_len + 1, 5)
ax.set_xticks(xticks)
ax.set_xticklabels(xticks)

ax.set_xlabel('Residue number')
ax.set_ylabel('Sequence Count')
Expand Down
25 changes: 25 additions & 0 deletions conkit/plot/_Figure.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,12 @@
__date__ = "07 Feb 2017"
__version__ = 0.1

from conkit.core import Contact
from conkit.core import ContactMap
from conkit.core import ContactFile
from conkit.core import Sequence
from conkit.core import SequenceFile


class Figure(object):
"""A Figure class to store common features
Expand Down Expand Up @@ -100,3 +106,22 @@ def prefix(self):
def prefix(self, prefix):
"""Define the prefix of the figure file"""
self._prefix = prefix

@staticmethod
def _check_hierarchy(h, t):
"""Check the hierarchy is of a specific type
Raises
------
TypeError
Provided hierarchy is not of specified type
ValueError
Type is unknown
"""
dict = {'Contact': Contact, 'ContactMap': ContactMap, 'ContactFile': ContactFile,
'Sequence': Sequence, 'SequenceFile': SequenceFile}
if t not in dict.keys():
raise ValueError("Type {0} is unknown".format(t))
elif not isinstance(h, dict[t]):
raise TypeError("Provided hierarchy is not a {0}".format(t))
66 changes: 66 additions & 0 deletions conkit/plot/tests/test__Figure.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
"""Testing facility for conkit.plot._Figure"""

__author__ = "Felix Simkovic"
__date__ = "08 Feb 2017"

from conkit.plot._Figure import Figure

import unittest


class Test(unittest.TestCase):

def test__init__(self):
f = Figure()
self.assertEqual(300, f.dpi)
self.assertEqual("png", f.format)
self.assertEqual("conkit", f.prefix)

f = Figure(dpi=20, format="svg")
self.assertEqual(20, f.dpi)
self.assertEqual("svg", f.format)
self.assertEqual("conkit", f.prefix)

self.assertRaises(ValueError, Figure, format="ooo")

def test_dpi(self):
f = Figure()
self.assertEqual(300, f.dpi)
f.dpi = 20
self.assertEqual(20, f.dpi)

def test_filename(self):
f = Figure()
self.assertEqual("conkit.png", f.file_name)
f.file_name = "test.eps"
self.assertEqual("test.eps", f.file_name)
self.assertEqual("eps", f.format)
self.assertEqual("test", f.prefix)
f.format = "pdf"
self.assertEqual("test.pdf", f.file_name)
self.assertEqual("pdf", f.format)
self.assertEqual("test", f.prefix)
self.assertRaises(ValueError, setattr, f, "file_name", "test.ooo")

def test_format(self):
f = Figure()
self.assertEqual("png", f.format)
f.format = "pdf"
self.assertEqual("pdf", f.format)
f.format = "ps"
self.assertEqual("ps", f.format)
f.format = "png"
self.assertEqual("png", f.format)
self.assertRaises(ValueError, setattr, f, "format", "bbb")

def test_prefix(self):
f = Figure()
self.assertEqual("conkit", f.prefix)
f.prefix = "test"
self.assertEqual("test", f.prefix)
f.prefix = "/path/to/prefix"
self.assertEqual("/path/to/prefix", f.prefix)


if __name__ == "__main__":
unittest.main(verbosity=2)
10 changes: 10 additions & 0 deletions docs/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ help:
@echo " pseudoxml to make pseudoxml-XML files for display purposes"
@echo " linkcheck to check all external links for integrity"
@echo " doctest to run all doctests embedded in the documentation (if enabled)"
@echo " figures to create all figures used in the documentation"

clean:
rm -rf $(BUILDDIR)/*
Expand Down Expand Up @@ -176,3 +177,12 @@ pseudoxml:
$(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml
@echo
@echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml."

figures:
mkdir _tmp
git clone https://github.com/rigdenlab/conkit-examples.git _tmp/conkit-examples
conkit.plot_map -o examples/images/toxd_cmap_simple.png _tmp/conkit-examples/toxd/toxd.fasta fasta _tmp/conkit-examples/toxd/toxd.mat ccmpred
conkit.plot_map -o examples/images/toxd_cmap_reference.png -p _tmp/conkit-examples/toxd/toxd.pdb _tmp/conkit-examples/toxd/toxd.fasta fasta _tmp/conkit-examples/toxd/toxd.mat ccmpred
conkit.plot_map -o examples/images/toxd_cmap_advanced.png -e _tmp/conkit-examples/toxd/toxd.psicov -ef psicov -p _tmp/conkit-examples/toxd/toxd.pdb _tmp/conkit-examples/toxd/toxd.fasta fasta _tmp/conkit-examples/toxd/toxd.mat ccmpred
conkit.plot_map -o examples/images/toxd_cmap_confidence.png --confidence -e _tmp/conkit-examples/toxd/toxd.psicov -ef psicov -p _tmp/conkit-examples/toxd/toxd.pdb _tmp/conkit-examples/toxd/toxd.fasta fasta _tmp/conkit-examples/toxd/toxd.mat ccmpred
rm -rf _tmp
Binary file modified docs/examples/images/toxd_cmap_advanced.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/examples/images/toxd_cmap_confidence.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/examples/images/toxd_cmap_reference.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/examples/images/toxd_cmap_simple.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading

0 comments on commit 0c35fcc

Please sign in to comment.