holoviz / holoviews

With Holoviews, your data visualizes itself.
https://holoviews.org
BSD 3-Clause "New" or "Revised" License
2.69k stars 402 forks source link

Support inverted label text option for Chord plot #4553

Open sayantan11995 opened 4 years ago

sayantan11995 commented 4 years ago

ALL software version info

holoviews=1.13.3, bokeh=2.1.1

Description of expected behavior and the observed behavior

The label texts in the left half of the chord plot getting inverted. inverted

It would be good if the default label text orientation can be made something like this image below: expected

Example code

import pandas as pd
import holoviews as hv
from holoviews import opts, dim
from bokeh.sampledata.les_mis import data

hv.extension('bokeh')
hv.output(size=300)

links = pd.DataFrame(data['links'])
nodes = hv.Dataset(pd.DataFrame(data['nodes']), 'index')
chord = hv.Chord((links, nodes)).select(value=(5, None))
chord.opts(
    opts.Chord(cmap='Category20', edge_cmap='Category20', edge_color=dim('source').str(), label_text_font_size='15px',
               labels='name', node_color=dim('index').str()))
jbednar commented 4 years ago

Well, the text isn't inverted, it's just arranged consistently in the orientation corresponding to its position. It makes sense to offer an option to flip the text in the way proposed here, and if someone wants to write the code for it I'd be happy to have that option. Whether it should be the default seems less clear; normally defaults should only be changed for a very good reason to avoid breaking things currently working, and I don't see any strong reason to prefer one or the other of the two approaches on principle.

philippjfr commented 4 years ago

I think a change in the default does seem warranted but I'd be happy to defer it to 2.0. Without looking at any of the code I think all that's needed is one modulo operator to avoid rotations beyond the -90-90 degree range.

As an aside the other nice thing that example shows is clustering and scaling points by the number of incoming/outgoing connections, which would also be nice features but would probably require a separate PR.

janrygl commented 3 years ago

Solution to overcome current behaviour:

def rotate_label(plot, element):    
    labels = plot.handles["labels"]
    for annotation in labels:        
        angle = annotation.get_rotation()
        if 90 < angle < 270:
            annotation.set_rotation(180 + angle)
            annotation.set_horizontalalignment("right")

chords.opts(cmap='Category20b',
           edge_cmap='Category20b', 
           edge_color=dim('source').str(), 
           labels='name', 
           node_color=dim('index').str(),
           hooks=[rotate_label]
           )
mullimanko commented 3 years ago

@janrygl, I tried your function and get the following error: WARNING:param.ChordPlot13794: Plotting hook <function rotate_label at 0x0000019D040C11F8> could not be applied:

'labels'

-- UPDATE --

janrygl's solution only works by selecting matplotlib as plotting library backend with hv.extension("matplotlib"), which is not clear from his answer. Otherwise the above-mentioned error occurs.

mullimanko commented 3 years ago

I wrote a function to rotate the label text also for bokeh as backend. Not perfect, but maybe useful: https://stackoverflow.com/a/65610161