KrishnaswamyLab / scprep

A collection of scripts and tools for loading, processing, and handling single cell data.
MIT License
72 stars 19 forks source link

add legend_ncol to scatter API #52

Closed dburkhardt closed 4 years ago

dburkhardt commented 5 years ago
import scprep
import numpy as np

data = np.random.normal(size=(100,2))
labels = np.random.choice(np.arange(12), size=100)
scprep.plot.scatter2d(data, labels)

image

Desired result:

image

Also this syntax was confusing

scprep.plot.tools.generate_legend(cmap={i:plt.cm.tab20(np.arange(20))[i] for i in range(12)}, ax=ax, ncol=2, bbox_to_anchor=(1,1))
scottgigante commented 5 years ago

You can achieve this with legend_anchor=(1,1) to scatter. However I believe scatter should already be doing ncol=2 for more than 10 labels - I'll look into that part.

What in particular is confusing about the generate_legend syntax?

scottgigante commented 5 years ago

Forgot to mention - the default placement is matplotlib's 'best' and I have no obvious game plan on how to improve on that. If you wanted you could dig into the API and work out if you can detect whether or not the legend plots over more than x% of points and if so use legend_anchor=(1, 1) by default, but that's beyond my time commitment.

dburkhardt commented 5 years ago

@scottgigante I'm okay with the matplotlib 'best' placement by default, but the legend isn't splitting into two columns by default. I just installed from dev today:

image

There's also no way to set the legend ncol from the scprep.plot.scatter() call

dburkhardt commented 4 years ago

Any idea what's going on here? I can try to test stuff

scottgigante commented 4 years ago

Sorry, it got lost because it didn't have a milestone attached. I'll have a dig.

scottgigante commented 4 years ago

Turns out I was using ncol = n // max_rows instead of ncol = ceil(n / max_rows). That's one part solved. The other part is should there be an API to access this from scatter. I'm open to input on that - there shouldn't be everything in the generic API because you can always do ax = scatter(legend=False) and then scprep.plot.tools.generate_legend(ax, ...) for super fine tuning, but this might be something that's common enough to want to include. Thoughts?