python-ternary icon indicating copy to clipboard operation
python-ternary copied to clipboard

area filling

Open altanir84 opened this issue 5 years ago • 6 comments

Great code.

Would be very helpfull to implement the tax.fill() feature, to create base plots with filled areas, like the Dickinson, 1970 Qt ternary plot. Thank you!

altanir84 avatar Jul 12 '19 15:07 altanir84

I manually implemented this by using some of the code for 'background' fill!

vmeschke avatar May 09 '21 00:05 vmeschke

Hi @vmeschke, do you want to share / contribute an example?

marcharper avatar May 12 '21 02:05 marcharper

@marcharper I would love to! What's the best way to do so?

vmeschke avatar May 20 '21 13:05 vmeschke

@vmeschke If you have an image and some code to generate it, you can add it to the examples directory. Otherwise you can paste the info here and I'll add it.

marcharper avatar May 23 '21 14:05 marcharper

Here's an example of code and the filling demo! I just modified the tax.fill method to take an unspecified number of points. I can talk more/add additional comments if helpful. filled_ternary

Code: import ternary import pandas as pd import math import itertools import numpy as np from pymatgen.core import Element, Composition from matplotlib import cm import matplotlib.pyplot as plt

def permute_point(p, permutation=None): """ Permutes the point according to the permutation keyword argument. The default permutation is "012" which does not change the order of the coordinate. To rotate counterclockwise, use "120" and to rotate clockwise use "201".""" if not permutation: return p return [p[int(permutation[i])] for i in range(len(p))]

def unzip(l): """[(a1, b1), ..., (an, bn)] ----> ([a1, ..., an], [b1, ..., bn])""" return list(zip(*l))

def project_point(p, permutation=None): """ Maps (x,y,z) coordinates to planar simplex. Parameters ---------- p: 3-tuple The point to be projected p = (x, y, z) permutation: string, None, equivalent to "012" The order of the coordinates, counterclockwise from the origin """ permuted = permute_point(p, permutation=permutation) a = permuted[0] b = permuted[1] x = a + b/2. y = (np.sqrt(3)/2) * b return np.array([x, y])

def fill_region(ax, color, points, pattern=None, zorder=-1000, alpha=None): """Draws a triangle behind the plot to serve as the background color for a given region.""" vertices = map(project_point, points) xs, ys = unzip(vertices) poly = ax.fill(xs, ys, facecolor=color, edgecolor=color, hatch=pattern, zorder=zorder, alpha=alpha) return poly

def main(): scale = 100 fontsize = 12 figure, tax = ternary.figure(scale=scale) tax.gridlines(color="grey", multiple=10)

# corner points of the regions. Any number of points works.
regions = [[(0, 0, 100), (25, 0, 75), (25, 50, 25)],
            [(25, 0, 75), (50, 50, 0), (30, 40, 30), (25, 50, 25)],
            [(50, 50, 0), (43, 57, 0), (25, 50, 25), (70, 10, 20)],
            [(40, 50, 10), (28.57, 71.43, 0), (25, 50, 25), (10, 80, 10), (20, 30, 50)]]

# Generating colors for the regions
cmap = cm.plasma
colorlist = []
for i in np.arange(0,1,1/len(regions)):
    colorlist.append(cmap(i))

# generate the filled regions and make them all different colors
colorindex = 0
for r in regions:
    fill_region(tax.get_axes(), color=colorlist[colorindex], points=r, alpha=.7)
    colorindex += 1

# Final plot formatting
tax.boundary(linewidth=2)
tax.get_axes().axis('off')
tax.clear_matplotlib_ticks()
tax.get_axes().set_aspect(1)
tax._redraw_labels()
tax.savefig('filled_ternary.png')

if name == 'main': main()

vmeschke avatar Jul 01 '21 16:07 vmeschke

If you add the following code to the 'ternary_axes_subplot.py' file, you should be able to call tax.fill_region() with the proper arguments and have it work ok. It works locally for me.

Additional Import: from .helpers import unzip

Method:

    def fill_region(self, color, points, pattern=None, zorder=-1000, alpha=None):
        """Draws a triangle behind the plot to serve as the background color
        for a given region."""
        ax = self.get_axes()
        vertices = map(project_point, points)
        xs, ys = unzip(vertices)
        poly = ax.fill(xs, ys, facecolor=color, edgecolor=color, hatch=pattern, zorder=zorder, alpha=alpha)
        return poly

vmeschke avatar Jul 01 '21 16:07 vmeschke