Source code for conkit.plot.tools

# BSD 3-Clause License
#
# Copyright (c) 2016-19, 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

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
from conkit.misc import deprecate

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 Warning ------- For multi-dimensional problems, see :func:`~scipy.signal.argrelmin`. Raises ------ :exc:`ValueError` Order needs to be >= 1! :exc:`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:`~matplotlib.axes.Axes` A :obj:`~matplotlib.axes.Axes` instance aspect_ratio : float The desired aspect ratio for :obj:`~matplotlib.axes.Axes` Returns ------- float The required aspect ratio to achieve the desired one Warning ------- 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)
@deprecate("0.11", msg="Use get_points_on_circle instead") def points_on_circle(*args, **kwargs): 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)