Source code for conkit.plot.tools

# BSD 3-Clause License
#
# Copyright (c) 2016-18, University of Liverpool
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# * Redistributions of source code must retain the above copyright notice, this
#   list of conditions and the following disclaimer.
#
# * Redistributions in binary form must reproduce the above copyright notice,
#   this list of conditions and the following disclaimer in the documentation
#   and/or other materials provided with the distribution.
#
# * Neither the name of the copyright holder nor the names of its
#   contributors may be used to endorse or promote products derived from
#   this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
"""Internal utility functions"""

__author__ = "Felix Simkovic"
__date__ = "16 Feb 2017"
__version__ = "0.1"

import numpy as np
import warnings

from conkit.core.contact import Contact
from conkit.core.contactmap import ContactMap
from conkit.core.contactfile import ContactFile
from conkit.core.sequence import Sequence
from conkit.core.sequencefile import SequenceFile


HierarchyIndex = {
    'Contact': Contact,
    'ContactMap': ContactMap,
    'ContactFile': ContactFile,
    'Sequence': Sequence,
    'SequenceFile': SequenceFile
}


[docs]class ColorDefinitions(object): """A class storing all color definitions for the various plots for fast and easy handling """ GENERAL = '#000000' MATCH = '#0F0B2C' MISMATCH = '#DC4869' STRUCTURAL = '#D8D6D6' L5CUTOFF = '#3F4587' L20CUTOFF = '#B5DD2B' PRECISION50 = L5CUTOFF FACTOR1 = L20CUTOFF AA_ENCODING = { 'A': '#882D17', 'C': '#F3C300', 'D': '#875692', 'E': '#F38400', 'F': '#A1CAF1', 'G': '#BE0032', 'H': '#C2B280', 'I': '#848482', 'K': '#008856', 'L': '#E68FAC', 'M': '#0067A5', 'N': '#F99379', 'P': '#604E97', 'Q': '#F6A600', 'R': '#B3446C', 'S': '#DCD300', 'T': '#8DB600', 'V': '#654522', 'W': '#E25822', 'Y': '#2B3D26', 'X': '#000000' }
[docs]def find_minima(data, order=1): """Find the minima in a 1-D list Parameters ---------- data : list, tuple A list of values order : int, optional The order, i.e. number of points next to point to consider Returns ------- list A list of indices for minima Warnings -------- For multi-dimensional problems, see :func:`scipy.signal.argrelmin`. Raises ------ ValueError Order needs to be >= 1! ValueError More than two elements required! """ if order < 1: raise ValueError("Order needs to be >= 1!") data = np.asarray(data) nelements = data.shape[0] if nelements < 2: raise ValueError("More than two elements required!") results = np.zeros(nelements, dtype=np.bool_) for i in np.arange(1, nelements - 1): start = 0 if i - order < 0 else i - order end = nelements if i + order + 1 > nelements else i + order + 1 results[i] = np.all(data[start:i] > data[i]) and np.all(data[i] < data[i + 1:end]) return np.where(results)[0].tolist()
[docs]def get_adjusted_aspect(ax, aspect_ratio): """Adjust the aspect ratio Parameters ---------- ax : :obj:`Axes <matplotlib.pyplot.Axes>` A :obj:`Axes <matplotlib.pyplot.Axes>` instance aspect_ratio : float The desired aspect ratio for :obj:`Axes <matplotlib.pyplot.Axes>` Returns ------- float The required aspect ratio to achieve the desired one Warnings -------- This function only works for non-logarithmic axes. """ default_ratio = (ax.get_xlim()[1] - ax.get_xlim()[0]) / (ax.get_ylim()[1] - ax.get_ylim()[0]) return float(default_ratio * aspect_ratio)
[docs]def points_on_circle(*args, **kwargs): warnings.warn("This function has been renamed to get_points_on_circle()") return get_points_on_circle(*args, **kwargs)
[docs]def get_points_on_circle(radius, h=0, k=0): """Calculate points on a circle with even spacing Parameters ---------- radius : int The radius of the circle h : int, optional The x coordinate of the origin k : int, optional The y coordinate of the origin Returns ------- list The list of coordinates for each point """ if radius == 0: return [[]] else: space = 2 * np.pi / radius coords = np.zeros((radius, 2)) for i in np.arange(radius): coords[i] = [round(h + radius * np.cos(space * i), 6), round(k + radius * np.sin(space * i), 6)] return coords.tolist()
[docs]def get_radius_around_circle(p1, p2): """Obtain the radius around a given circle Parameters ---------- p1 : list, tuple Point 1 p2 : list, tuple Point 2 adjacent `p1` Returns ------- float The radius for points so p1 and p2 do not intersect """ dist = np.linalg.norm(np.array(p1) - np.array(p2)) return dist / 2.0 - dist * 0.1
def _isinstance(hierarchy, hierarchy_type): """Confirm the data structure to be a ConKit definition""" if isinstance(hierarchy_type, str) and hierarchy_type in HierarchyIndex: return isinstance(hierarchy, HierarchyIndex[hierarchy_type]) else: return isinstance(hierarchy, hierarchy_type)