KrishnaswamyLab / scprep

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

How to re-order legends when using scprep.plot.rotate_scatter3 #100

Open scottgigante opened 4 years ago

scottgigante commented 4 years ago

From @simonewebb at https://github.com/KrishnaswamyLab/PHATE/issues/87 :

I am loving the output of PHATE for my dataset so far - great tool (thanks for your work on this).

Currently, I am trying to visually tweak the output of scprep.plot.rotate_scatter3d, in order that it looks a bit more pleasing. I have altered it as follows, and am very nearly happy with the result:

mpl.rcParams['animation.embed_limit'] = 2**256

scprep.plot.rotate_scatter3d(Y_phate_3d, c=labels, figsize=(15,10), label_prefix="PHATE", cmap=new_colors_3d, legend_title="Fetal BM cell types", title="PHATE visualisation of FBM progenitor differentiation", elev=10, azim=10, legend_loc=[0.75,0.55], filename='phate_dpi_v11.mp4', rotation_speed=20, fps=60, dpi=400, ticklabels=False)

where:

labels = adata.obs["cell.labels_comb"].astype("object") and new_colors_3d = ['#c37d00', '#009500', '#fba100', '#0754ab', '#ffa0ff', '#a900a9', '#aaffaa', '#9ccbfc', '#e80000']

Good so far, but, the order of the legend labels are coming up in an order that is unintuitive to the biology. I'd like to alter this, and began by first attempting to alter the order of the categories given to "labels", from c=labels. However, this made no difference.

Could you please direct me to the best way to alter the order - or what arg would be responsible for the placement of this?

Would be very useful and improve the output a lot!

Thanks

Simone

*PS: if you have any ideas WRT altering amount of white space to the left and right of the .mp4 output that would also be very much appreciated

scottgigante commented 4 years ago

The easiest way to customise the legend is by turning off the default legend and creating your own using scprep.plot.tools.generate_legend and a dictionary colormap. You can do this as follows:

import matplotlib as mpl
import numpy as np
import scprep

mpl.rcParams["animation.embed_limit"] = 2 ** 256

# generate data
data = np.random.normal(0, 1, (100, 3))
labels = np.random.choice(len(colors), data.shape[0], replace=True)

label_list = np.unique(labels)  # reorder this to change legend order
colors = [
    "#c37d00",
    "#009500",
    "#fba100",
    "#0754ab",
    "#ffa0ff",
    "#a900a9",
    "#aaffaa",
    "#9ccbfc",
    "#e80000",
]  # reorder this to change colors associated with labels

cmap = dict()
for i, label in enumerate(label_list):
    cmap[label] = colors[i]

# this is what a dictionary cmap should look like
print(cmap)

# prepare axis by plotting data and creating legend
ax = scprep.plot.scatter3d(
    data,
    c=labels,
    figsize=(15, 10),
    label_prefix="PHATE",
    cmap=cmap,
    ticks=False,
    legend=False,
    title="PHATE visualisation of FBM progenitor differentiation",
)
scprep.plot.tools.generate_legend(
    ax=ax, cmap=cmap, loc=[0.75, 0.55], title="Fetal BM cell types"
)

# create animation
scprep.plot.rotate_scatter3d(
    data,
    c=labels,
    ax=ax,
    label_prefix="PHATE",
    cmap=cmap,
    ticks=False,
    legend=False,
    elev=10,
    azim=10,
    filename="phate_dpi_v11.mp4",
    rotation_speed=20,
    fps=60,
    dpi=400,
)
simonewebb commented 4 years ago

Hi Scott,

Your advice has worked a treat - thank you so much (and for the very swift reply)

Do you have any recommendations for altering the amount of white space surrounding the fig when saved as mp4 (i.e., how i could possibly increase or decrease white space to the left/right hand side of the rotating grid?)

Thanks

Simone

scottgigante commented 4 years ago

Ah sorry I forgot about that part of the question! This stackoverflow answer might help you, though I'm not very experienced with this.

simonewebb commented 4 years ago

Amazing, thanks so much, Scott