Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Heatmap scale greater than 1 vs less than equal to 1 #191

Closed
bmondal94 opened this issue Apr 5, 2022 · 4 comments
Closed

Heatmap scale greater than 1 vs less than equal to 1 #191

bmondal94 opened this issue Apr 5, 2022 · 4 comments

Comments

@bmondal94
Copy link

I wanted to draw a heatmap with scale 1.

import ternary
import random
def generate_random_heatmap_data(scale=5):
    from ternary.helpers import simplex_iterator
    d = dict()
    for (i,j,k) in simplex_iterator(scale):
        d[(i,j,k)] = random.random()
    return d

scale = 10
d = generate_random_heatmap_data(scale)
dd = {tuple(np.array(x[0])/scale): x[1] for x in d.items()}
#------------------------------------------------------------------------------
figure, tax = ternary.figure(scale=scale)
figure.set_size_inches(10, 8)
tax.heatmap(d, style="h")
tax.boundary()
tax.clear_matplotlib_ticks()
tax.get_axes().axis('off')
tax.set_title(f"Heatmap Test: Hexagonal (scale={tax.get_scale()})")

#------------------------------------------------------------------------------
figure, tax = ternary.figure(scale=1)
figure.set_size_inches(10, 8)
tax.heatmap(dd, style="h")
tax.boundary()
tax.clear_matplotlib_ticks()
tax.get_axes().axis('off')
tax.set_title(f"Heatmap Test: Hexagonal (scale={tax.get_scale()})")

But as the hexagonal tile corners in the function 'generate_hexagon_deltas()' are fixed by factor of 1, the heatmap drawing was not as expected. So, I updated 2 of the functions as below:

def hexagon_coordinates(i, j, k, factor):
    .
    .
    .
    signature = ""
    for x in [i, j, k]:
        if round(x, 6) == 0: #--This is to avoid flotting point precision
            signature += "0"
        else:
            signature += "1"
    .
    .
    .
    return np.array([center + x*factor for x in deltas])


def polygon_generator(data, scale, style, permutation=None):
    .
    .
    .
    #-- This factor will be used to scale the polygon corner coordinates
    factor = 1 if scale > 1 else 0.1*scale
    .
    .
    .
         if style == 'h':
                .
                .
                .
                vertices = hexagon_coordinates(i, j, k, factor)
                yield map(project_point, vertices), value
         elif style == 'd':
    ...

Now things are better. Any comments or alternative suggestions?

@marcharper
Copy link
Owner

The existing ternary heatmap function isn't intended to work with scale = 1. It assumes that you'll define your own triangulation of the simplex and compute the desired value for each i, j, k combination, much like heatmapf does if you supply a function that can compute the values. In this case scale controls how many lattice points of the simplex to evaluate, much like the gridsize parameter in matplotlib's hexbin function (but hexbin is otherwise more of a histogram).

@ericwhester
Copy link

Is there some way that we can at least rescale the axes/axis ticks to go from 0 to 1 while also getting heatmapf to work?

@bmondal94
Copy link
Author

Approach-1: Update the source code as mentioned in #191 (comment) .
Approach-2: Calculate the heatmap data with scale 100 but set the tick labels with scale 1.

import random
import numpy as np
'''
Principle: Creating heatmap w.r.t scale=100 but label the ticks with scale=1.
'''

def generate_random_heatmap_data(scale=5):
    from ternary.helpers import simplex_iterator
    d = dict()
    for (i,j,k) in simplex_iterator(scale):
        d[(i,j,k)] = random.random()
    return d

scale = 100
d = generate_random_heatmap_data(scale)
dd = {tuple(np.array(x[0])/scale): x[1] for x in d.items()}
#------------------------------------------------------------------------------
figure, tax = ternary.figure(scale=scale)
figure.set_size_inches(10, 8)
tax.heatmap(d, style="h")
tax.boundary()
tax.clear_matplotlib_ticks()
tax.get_axes().axis('off')
tax.set_title(f"Heatmap Test: Hexagonal (original scale={tax.get_scale()})")

# ------------- Create tick labels with scale 1 --------------------------
TickLabels = list(np.linspace(0,1,11,dtype=float)) 
tax.ticks(ticks=TickLabels, multiple=10, tick_formats={'b':'%.1f','l':'%.1f','r':'%.1f'})

@ericwhester
Copy link

ericwhester commented Apr 28, 2022

Thanks for the tip on adjusting the ticks.

I also found another alternative: use plt.tripcolors with a rescaled version of the points (derived from simplex_iterator) on tax.ax (where tax has scale 1).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants