Source code for mgkit.plots.abund

"""
.. versionadded:: 0.1.15

Module to plot relative abundances in a 1D or 3D projection
"""
from __future__ import division
from builtins import zip
import math

import numpy

SQRT3_2 = math.sqrt(3) / 2


[docs]def draw_triangle_grid(ax, labels=['LAM', 'SAM', 'EAM'], linewidth=1., styles=['-', ':', '--'], fontsize=22): """ .. versionchanged:: 0.2.0 reworked internals and changed defaults Draws a triangle as axes, for a planar-simplex projection. Arguments: ax: an axis instance labels (iterable): list of string to be put for the axes styles (None, iterable): either *None* for solid lines or matplotlib line markers. These are in sync between the internal lines and the axes. linewidth (float): line width for the axes, the internal lines are equal to *0.75 * linewidth* fontsize (float): font size for the labels, the tick font size is equal to *0.75 * fontsize* """ ax.set_ylim((-0.1, 1.0)) ax.set_xlim((-0.1, 1.1)) ax.set_axis_off() # SAM ax.text(0, -0.05, labels[0], fontsize=fontsize, ha='right') # LAM ax.text(1.0, -0.05, labels[1], fontsize=fontsize, ha='left') # EAB ax.text(0.5, SQRT3_2 + 0.025, labels[2], fontsize=fontsize, ha='center') values = numpy.arange(0.1, 1., 0.1) points = [] # Bottom axis (LAM) x1, y1 = project_point((1, 0, 0)) x2, y2 = project_point((0, 1, 0)) points.append(( [x1, x2], [y1, y2] )) # Left axis (EAM) x1, y1 = project_point((1, 0, 0)) x2, y2 = project_point((0, 0, 1)) points.append(( [x1, x2], [y1, y2] )) # Right axis (SAM) x1, y1 = project_point((0, 1, 0)) x2, y2 = project_point((0, 0, 1)) points.append(( [x1, x2], [y1, y2] )) if styles is None: styles = ['-'] * 3 for (X, Y), style in zip(points, styles): ax.plot(X, Y, linestyle=style, linewidth=linewidth*1.5, color='k') for index in values: x1, y1 = project_point((index, 1 - index, 0)) x2, y2 = project_point((0, 1 - index, index)) # EAM ax.plot([x1, x2], [y1, y2], linestyle=styles[2], color='k', linewidth=linewidth) x3, y3 = project_point((0, index, 1 - index)) x4, y4 = project_point((index, 0, 1 - index)) # SAM ax.plot([x3, x4], [y3, y4], linestyle=styles[1], color='k', linewidth=linewidth) # LAM ax.plot([x4, x1], [y4, y1], linestyle=styles[0], color='k', linewidth=linewidth) # LAM labels ax.text(x1, y1 - 0.02, numpy.round(index, 1), va='top', ha='center', fontsize=int(fontsize * 0.75)) # EAM labels ax.text(x4 - 0.02, y4, numpy.round(1 - index, 1), ha='right', va='center', fontsize=int(fontsize * 0.75)) # EAM labels ax.text(x3 + 0.02, y3, numpy.round(index, 1), ha='left', va='center', fontsize=int(fontsize * 0.75))
[docs]def draw_1d_grid(ax, labels=['LAM', 'SAM'], fontsize=22): """ .. versionchanged:: 0.2.0 reworked internals and changed defaults Draws a 1D axis, to display propotions. Arguments: ax: an axis instance labels (iterable): list of string to be put for the axes fontsize (float): font size for the labels, the tick font size is equal to *0.75 * fontsize* """ ax.set_ylim((-1.1, 1.1)) ax.set_xlim((-0.1, 1.1)) ax.set_axis_off() ax.text(-0.025, 0, labels[0], fontsize=fontsize, va='center', ha='right') ax.text(1.025, 0, labels[1], fontsize=fontsize, va='center', ha='left') ty = 1.0 by = -1.0 ax.plot([0, 1], [0, 0], linewidth=1, color='k') for x in numpy.arange(0.1, 1., 0.1): ax.plot([x, x], [by, ty], color='k', linestyle=':') y_b = by - .1 y_t = ty + .1 ax.text(x, y_b, numpy.round(x, 1), fontsize=fontsize * 0.75, ha='center', va='top') ax.text(x, y_t, numpy.round(1 - x, 1), fontsize=fontsize * 0.75, ha='center', va='bottom')
[docs]def project_point(point): """ Project a tuple containing coordinates (i.e. x, y, z) to planar-simplex. Arguments: point (tuple): contains the three coordinates to project Returns: tuple: the projected point in a planar-simplex """ # a = point[0] b = point[1] c = point[2] x = b + (c / 2.) y = SQRT3_2 * c return (x, y)
[docs]def col_func_firstel(key, colors=None): if colors is None: return 'black' return colors[key[0]]
[docs]def col_func_name(key, func=None, colors=None): if (colors is None): return 'black' if func is not None: key = func(key) return colors[key]
[docs]def col_func_taxon(taxon_id, taxonomy, anc_ids, colpal): for anc_id, color in zip(anc_ids, colpal): if taxonomy.is_ancestor(taxon_id, anc_id): return color return 'black'
[docs]def draw_circles(ax, data, col_func=col_func_name, csize=200, alpha=.5, sizescale=None, order=None, linewidths=0., edgecolor='none'): """ .. versionchanged:: 0.2.0 changed internals and added return value Draws a scatter plot over either a planar-simplex projection, if the number of coordinates is 3, or in a 1D axis. If the number of coordinates is 3, :func:`project_point` is used to project the point in 2 coordinates. The coordinates are converted in proportions internally. Arguments: ax: axis to plot on data (pandas.DataFrame): a DataFrame with 2 for a 1D plot or 3 columns for a planar-simplex col_func (func): a function that accept a parameter, an element of the DataFrame index and returns a colour for it csize (int): the base size of the circles alpha (float): transparency of the circles, between 0 and 1 included sizescale (None, pandas.Series): a Series or dictionary with the same elements as the Index of *data*, whose values are the size factors that are multiplied to *csize*. If **None**, the size of the circles is equal to *csize* order (None, iterable): iterable with the elements of *data* Index, to specify the order in which the circles must be plotted. If None, the order is the same as *data.index* linewidths (float): width of the circle line edgecolor (str): color of the circle line Returns: PathCollection: the return value of matplotlib *scatter* .. note:: To **not** have circle lines, *edgecolor* must be *'none'* and *linewidths* equal *0* """ # normalize data (ternary plots requires that the sum of a row is 1) data = data.div(data.sum(axis=1), axis=0) def no_project(a, b): if a > b: x = 1 - a else: x = b return x, 0. if order is None: order = data.index X = [] Y = [] for key, coord in data.loc[order].iterrows(): # print coord x, y = project_point(coord) if len(coord) == 3 else no_project(*coord) X.append(x) Y.append(y) colors = [col_func(key) for key in order] paths = ax.scatter( X, Y, color=colors, alpha=alpha, linewidths=linewidths, edgecolor=edgecolor, marker=u'o', s=csize * (sizescale.loc[order] if sizescale is not None else 1) ) return paths
[docs]def draw_axis_internal_triangle(ax, color='r', linewidth=2.): """ .. versionadded:: 0.2.5 Draws a triangle that indicates the 50% limit for all 3 samples Arguments: ax: axis to use color (str, float, tuple): color used to draw the triangle linewidth (float): line width """ x1, y1 = project_point([.5, .5, 0.]) x2, y2 = project_point([.5, 0., 0.5]) x3, y3 = project_point([.0, 0.5, 0.5]) ax.plot( [x1, x2, x3, x1], [y1, y2, y3, y1], color=color, linewidth=linewidth )