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

Make base color white #22

Open
cbelth opened this issue Oct 8, 2018 · 7 comments
Open

Make base color white #22

cbelth opened this issue Oct 8, 2018 · 7 comments

Comments

@cbelth
Copy link

cbelth commented Oct 8, 2018

Is there any way to make the color corresponding with 0 density white and have the color approach red as the density increases?

@astrofrog
Copy link
Owner

@cbelth - I think you should be able to pass color='red' to the scatter_density method - does that work? See the second example in this section: https://github.com/astrofrog/mpl-scatter-density#scatter_density-method

@cbelth
Copy link
Author

cbelth commented Oct 8, 2018

That makes the background white, but there is no discernible gradient from light red to dark red so all densities look the same.

@astrofrog
Copy link
Owner

@cbelth - could you show your example here? (code and plot). Normally there should be a gradient, but I wonder if somehow the max/min values for the density aren't being chosen correctly.

@biprateep
Copy link

I think I also want something similar. Is it possible to use a cmap like vridis where the color is applied only to the region where the data points are present? Something like this:
image

@fohrloop
Copy link

I used the LinearSegmentedColormap to create viridis-like colormap with white base color ("from 0 to 1e-20"). I don't know if there are better options.

from matplotlib.colors import LinearSegmentedColormap

white_viridis = LinearSegmentedColormap.from_list('white_viridis', [
    (0, '#ffffff'),
    (1e-20, '#440053'),
    (0.2, '#404388'),
    (0.4, '#2a788e'),
    (0.6, '#21a784'),
    (0.8, '#78d151'),
    (1, '#fde624'),
], N=256)

ax = fig.add_subplot(1, 1, 1, projection='scatter_density')
density = ax.scatter_density(x, y, cmap=white_viridis)
fig.colorbar(density, label='Number of points per pixel')

Example:

image

@biprateep
Copy link

@np-8 That does the job for me! Thanks a lot!

@joseph-sch
Copy link

There is a function set_under(...) in Matplotlib's Colormap class to set the color and transparency of values which are under vmin (there is also set_over(...) for values above vmax and set_bad(...) for masked values).

So you can use set_under(alpha=0) in conjunction with a vmin value above 0 (I found that 0.5 gives a good result). When you specify vmin to scatter_density, you have to specify vmax as well, but you can use the same as the default, i.e. np.nanmax:

import numpy as np
import matplotlib.pyplot as plt
import mpl_scatter_density
from matplotlib import cm
import copy

cmap = copy.copy(cm.get_cmap("viridis"))
cmap.set_under(alpha=0)

data = np.random.multivariate_normal([0, 0], [[1, 2.85], [2.85, 9]], 1000000)

x, y = data[:, 0], data[:, 1]

fig = plt.figure()
ax = fig.add_subplot(1, 1, 1, projection='scatter_density')
density = ax.scatter_density(x, y, cmap=cmap, 
                             vmin=0.5, vmax=np.nanmax,
                             dpi=150, downres_factor=2)
cb = fig.colorbar(density, label='Number of points per pixel')

image

In my case, the goal was to imitate plots typically used in Flow Cytometry. The requirements that the background be white where density is zero and that individual data points (outliers) be clearly visible are met with @np-8's trick or with the solution I propose above. Beyond that, I found that the "jet" colormap with a LogNorm normalization worked best; for vmin the value is 0.5 like above and for vmax, in that case, you have to provide a constant but I found that x.size as the upper limit is satisfactory.

from matplotlib.colors import LogNorm

cmap = copy.copy(cm.get_cmap("jet"))
cmap.set_under(alpha=0)

fig = plt.figure()
ax = fig.add_subplot(1, 1, 1, projection='scatter_density')
density = ax.scatter_density(x, y, cmap=cmap, 
                             norm=LogNorm(vmin=0.5, vmax=x.size),
                             dpi=36, downres_factor=2)
cb = fig.colorbar(density, label='Number of points per pixel')

image

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

5 participants