pygraphistry icon indicating copy to clipboard operation
pygraphistry copied to clipboard

[FEA] luminosity encoding

Open lmeyerov opened this issue 3 years ago • 0 comments

Is your feature request related to a problem? Please describe.

In some scenarios, an extra dimension can help, and luminosity is one of them. Additional, a secondary key for normalization can also help.

Describe the solution you'd like

Something like:

import math, numpy as np

def with_coloring(base_g, point_colors: dict, point_color_default: int):
   """
   sets base color by base_g._nodes.type and then luminosity by inferred degree 
   """

    #log-scale 'g2._nodes.degree'
    g2 = base_g.nodes(base_g._nodes[[base_g._node, 'type']].reset_index(drop=True)).get_degrees()
    g2 = g2.nodes(g2._nodes.assign(degree=pd.Series(np.log(g2._nodes['degree'].values))))
    degs = g2._nodes.degree

    colors = g2._nodes['type'].map(point_colors).fillna(point_color_default).astype('int64')

    # color multiplier: color_final = color_base * (min_luminosity + (1 - min_luminosity) * multiplier)
    min_luminosity = 0.5
    type_to_min_degree = g2._nodes.groupby('type').agg({'degree': 'min'}).to_dict()['degree']
    type_to_max_degree = g2._nodes.groupby('type').agg({'degree': 'max'}).to_dict()['degree']
    mns = g2._nodes['type'].map(type_to_min_degree)
    mxs = g2._nodes['type'].map(type_to_max_degree)
    multiplier = (degs - mns + 1.0) / (mxs - mns + 1.0)
    multiplier = min_luminosity + (1 - min_luminosity) * multiplier

    rgbs_arr = [
        pd.Series(c & 255, dtype='int')
        for c in [colors.values >> 16, colors.values >> 8, colors.values]
    ]
    weighted_arr = [
        pd.Series(np.floor((c * multiplier).values)).round().astype('int64').values
        for c in rgbs_arr
    ]

    rgb = (weighted_arr[0]<<24) | (weighted_arr[1]<<16) | (weighted_arr[2]<<8)
    colors = pd.Series(rgb, dtype='int64')

    return (base_g
            .nodes(base_g._nodes.reset_index().assign(pc=colors))
            .bind(point_color='pc'))

Describe alternatives you've considered

Via just pygraphistry

  • note how this works off of a known computed per-entity color; would be better if not
  • with and without log scaling
  • luminosity can really be by mixing in black, white, or some other color
  • with and without secondary dimension ("degree" vs "degree partitioned by type")
  • default on degree

Via backend:

  • enables legend support & multi-client
  • server likely would reuse this impl, so a good start

lmeyerov avatar Apr 14 '22 07:04 lmeyerov