Skip to content

Commit

Permalink
1.3.2
Browse files Browse the repository at this point in the history
  • Loading branch information
erdogant committed May 27, 2023
1 parent 27300f1 commit aa09516
Show file tree
Hide file tree
Showing 3 changed files with 89 additions and 63 deletions.
6 changes: 2 additions & 4 deletions scatterd/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,14 @@

__author__ = 'Erdogan Tasksen'
__email__ = '[email protected]'
__version__ = '1.3.1'
__version__ = '1.3.2'

# module level doc-string
__doc__ = """
scatterd
=====================================================================
Description
-----------
Scatterd is an easy and fast way of creating scatter plots.
Scatterd is an easy and fast way of creating beautiful scatter plots.
Examples
--------
Expand Down
29 changes: 20 additions & 9 deletions scatterd/examples.py
Original file line number Diff line number Diff line change
@@ -1,28 +1,39 @@
from scatterd import scatterd, import_example
import numpy as np

# %%
X, y = make_friedman1(n_samples=100000, n_features=5, random_state=0)
fig, ax = scatterd(X[:,0], X[:,1], density=False, s=0)

df = import_example()
fig, ax = scatterd(df['tsneX'],
df['tsneY'],
labels=df['labx'],
)

# %%

from scatterd import scatterd, import_example
df = import_example()
fig, ax = scatterd(df['tsneX'],
df['tsneY'],
labels=df['labx'],
density=True,
density_on_top=True,
args_density={'alpha': 0.3},
gradient='#FFFFFF',
edgecolor='#FFFFFF',
density_on_top=False,
# args_density={'alpha': 0.3},
gradient='opaque',
# gradient='#FFFFFF',
edgecolor='#000000',
grid=True,
fontweight='normal',
fontsize=26,
legend=2,
)

# %%
# X, y = make_friedman1(n_samples=100000, n_features=5, random_state=0)
# fig, ax = scatterd(X[:,0], X[:,1], density=False, s=0)


# %%




# %%
# Import example iris dataet
Expand Down
117 changes: 67 additions & 50 deletions scatterd/scatterd.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,21 +22,21 @@ def scatterd(x,
y,
z=None,
s=150,
c=[0,0.1,0.4],
c=[0, 0.1, 0.4],
labels=None,
marker='o',
alpha=0.8,
edgecolor='#000000',
gradient=None,
density=False,
gradient='opaque',
density=True,
density_on_top=False,
norm=False,
cmap='tab20c',
figsize=(25, 15),
dpi=100,
legend=None,
jitter=None,
xlabel='x-axis', ylabel='y-axis', title='', fontsize=24, fontcolor=None, grid=False, fontweight='normal',
xlabel='x-axis', ylabel='y-axis', title='', fontsize=24, fontcolor=None, grid=True, fontweight='normal',
args_density = {'cmap': 'Reds', 'fill': True, 'thresh': 0.05, 'bw_adjust': .6, 'alpha': 0.66, 'legend': False, 'cbar': False},
visible=True,
fig=None,
Expand Down Expand Up @@ -70,9 +70,11 @@ def scatterd(x,
* 'face': The edge color will always be the same as the face color.
* 'none': No patch boundary will be drawn.
* '#FFFFFF' : A color or sequence of colors.
gradient : String, (default: None)
Hex color to make a lineair gradient for the scatterplot.
'#FFFFFF'
gradient : String, (default: 'opaque')
Hex color to make a lineair gradient using the density.
* None: Do not use gradient.
* opaque: Towards the edges the points become more opaque and thus not visible.
* '#FFFFFF': Towards the edges it smooths into this color
density : Bool (default: False)
Include the kernel density in the scatter plot.
density_on_top : bool, (default: False)
Expand Down Expand Up @@ -188,13 +190,13 @@ def scatterd(x,
# Preprocessing
X, labels = _preprocessing(x, y, z, labels, jitter, norm)
# Set color
c_rgb = set_colors(X, labels, c, cmap, gradient=gradient, verbose=verbose)
c_rgb, opaque = set_colors(X, labels, c, cmap, gradient=gradient, verbose=verbose)
# Set fontcolor
fontcolor = set_fontcolor(fontcolor, labels, X, cmap, verbose=2)
# Set size
s = set_size(X, s)
# Set size
alpha = set_alpha(X, alpha)
alpha = set_alpha(X, alpha, gradient, opaque, verbose)
# Set marker
marker = set_marker(X, marker)
# Bootup figure
Expand Down Expand Up @@ -241,6 +243,7 @@ def _set_figure_properties(X, labels, fontcolor, fontsize, xlabel, ylabel, title
# Set axis fontsizes
if grid is None: grid=False
if grid is True: grid='#dddddd'
None if zorder is None else zorder + 1
font = {'family': 'DejaVu Sans', 'weight': fontweight, 'size': fontsize}
matplotlib.rc('font', **font)
for item in ([ax.title, ax.xaxis.label, ax.yaxis.label] + ax.get_xticklabels() + ax.get_yticklabels()):
Expand All @@ -252,7 +255,7 @@ def _set_figure_properties(X, labels, fontcolor, fontsize, xlabel, ylabel, title
# Compute median for better center compared to mean
XYmean = np.mean(X[labels==uilabel, :], axis=0)
if X.shape[1]==2:
ax.text(XYmean[0], XYmean[1], str(uilabel), color=fontcolor.get(uilabel), fontdict={'weight': fontweight, 'size': fontsize}, zorder=zorder+1)
ax.text(XYmean[0], XYmean[1], str(uilabel), color=fontcolor.get(uilabel), fontdict={'weight': fontweight, 'size': fontsize}, zorder=zorder)
else:
ax.text(XYmean[0], XYmean[1], XYmean[2], str(uilabel), color=fontcolor.get(uilabel), fontdict={'weight': fontweight, 'size': fontsize})

Expand Down Expand Up @@ -282,6 +285,8 @@ def set_colors(X, labels, c, cmap='tab20c', gradient=None, verbose=3):

# The default is all dots to black
c_rgb = np.repeat([0, 0, 0], X.shape[0], axis=0).reshape(-1, 3)
# Create opaque levels
opaque = np.array([0.0] * X.shape[0])

# Change on input c
if len(c)==1 and isinstance(c, list): c = c[0]
Expand All @@ -297,51 +302,59 @@ def set_colors(X, labels, c, cmap='tab20c', gradient=None, verbose=3):
# Create unqiue colors for labels if there are multiple classes or in case cmap and gradient is used.
if verbose>=4: print('[scatterd] >Colors are based on the input [labels] and on [cmap].')
if labels is None: labels = np.repeat(0, X.shape[0])
c_rgb, _ = colourmap.fromlist(labels, cmap=cmap, method='matplotlib', gradient=gradient)
c_rgb = colourmap.fromlist(labels, X=X, cmap=cmap, method='matplotlib', gradient=gradient)[0]

# Add gradient for each class
if (gradient is not None):
if verbose>=4: print('[scatterd] >Color [gradient] is included.')
c_rgb = gradient_on_density_color(X, c_rgb, labels)
# if (gradient is not None):
# if verbose>=4: print('[scatterd] >Color [gradient] is included.')
# c_rgb = gradient_on_density_color(X, c_rgb, labels)

if gradient=='opaque' and c_rgb.shape[1]==4:
opaque = c_rgb[:, -1]
c_rgb = c_rgb[:, :3]

# Return
return c_rgb
return c_rgb, opaque


# %% Create gradient based on density.
def gradient_on_density_color(X, c_rgb, labels):
"""Set gradient on density color."""
if labels is None: labels = np.repeat(0, X.shape[0])
from scipy.stats import gaussian_kde
uilabels = np.unique(labels)
density_colors= np.repeat([1., 1., 1.], len(labels), axis=0).reshape(-1, 3)

if (len(uilabels)!=len(labels)):
for label in uilabels:
idx = np.where(labels==label)[0]
if X.shape[1]==2:
xy = np.vstack([X[idx, 0], X[idx, 1]])
else:
xy = np.vstack([X[idx, 0], X[idx, 1], X[idx, 2]])

try:
# Compute density
z = gaussian_kde(xy)(xy)
# Sort on density
didx = idx[np.argsort(z)[::-1]]
except:
didx=idx

# order colors correctly based Density
density_colors[didx] = c_rgb[idx, :]
# plt.figure()
# plt.scatter(X[didx,0], X[didx,1], color=c_rgb[idx, :])
# plt.figure()
# plt.scatter(idx, idx, color=c_rgb[idx, :])
c_rgb=density_colors

# Return
return c_rgb
# def gradient_on_density_color(X, c_rgb, labels, showfig=False):
# """Set gradient on density color."""
# if labels is None: labels = np.repeat(0, X.shape[0])
# from scipy.stats import gaussian_kde
# uilabels = np.unique(labels)
# # density_colors = np.repeat([1., 1., 1.], len(labels), axis=0).reshape(-1, 3)
# density_colors = np.ones_like(c_rgb)

# if (len(uilabels)!=len(labels)):
# for label in uilabels:
# idx = np.where(labels==label)[0]
# if X.shape[1]==2:
# xy = np.vstack([X[idx, 0], X[idx, 1]])
# else:
# xy = np.vstack([X[idx, 0], X[idx, 1], X[idx, 2]])

# try:
# # Compute density
# z = gaussian_kde(xy)(xy)
# # Sort on density
# didx = idx[np.argsort(z)[::-1]]
# except:
# didx=idx

# # order colors correctly based Density
# density_colors[didx] = c_rgb[idx, :]

# if showfig:
# plt.figure()
# fig, ax = plt.subplots(1,2, figsize=(20,10))
# ax[0].scatter(X[didx,0], X[didx,1], color=c_rgb[idx, 0:3], alpha=c_rgb[idx, 3], edgecolor='#000000')
# ax[1].scatter(idx, idx, color=c_rgb[idx, 0:3], alpha=c_rgb[idx, 3], edgecolor='#000000')

# c_rgb=density_colors

# # Return
# return c_rgb


# %% Fontcolor
Expand Down Expand Up @@ -414,10 +427,14 @@ def set_size(X, s):
return s


def set_alpha(X, alpha):
def set_alpha(X, alpha, gradient, opaque, verbose):
"""Set alpha."""
if alpha is None: alpha=0.8
if isinstance(alpha, (int, float)): alpha = np.repeat(alpha, X.shape[0])
if isinstance(alpha, (int, float)):
alpha = np.repeat(alpha, X.shape[0])
if gradient=='opaque':
if verbose>=3: print('[scatterd]> Set alpha based on density because of the parameter: [%s]' %(gradient))
alpha = opaque
# Minimum size should be 0 (dots will not be showed)
alpha = np.maximum(alpha, 0)
return alpha
Expand Down

0 comments on commit aa09516

Please sign in to comment.