Skip to content

Commit

Permalink
Added plotting function for Sweep objects
Browse files Browse the repository at this point in the history
  • Loading branch information
ejohnson643 committed Nov 3, 2021
1 parent 6499b68 commit 385c37b
Show file tree
Hide file tree
Showing 5 changed files with 816 additions and 76 deletions.
259 changes: 249 additions & 10 deletions EMBEDR/embedr.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from EMBEDR._affinity import calculate_kEff as _calc_kEff_from_sparse
import EMBEDR.callbacks as cb
import EMBEDR.ees as ees
from EMBEDR.human_round import *
import EMBEDR.nearest_neighbors as nn
import EMBEDR.plotting_utility as putl
from EMBEDR.tsne import tSNE_Embed
Expand Down Expand Up @@ -1945,12 +1946,7 @@ def plot(self,
else:
Y = self.null_Y[embed_2_show]

[pVal_cmap,
pVal_cnorm] = putl.make_categ_cmap(change_points=pVal_clr_change)

color_bounds = np.linspace(pVal_clr_change[0],
pVal_clr_change[-1],
pVal_cmap.N)
pVal_cmap = putl.CategoricalFadingCMap(change_points=pVal_clr_change)

pVals = -np.log10(self.pValues)

Expand All @@ -1959,8 +1955,8 @@ def plot(self,
h_ax = ax.scatter(*Y[sort_idx].T,
s=scatter_s,
c=pVals[sort_idx],
cmap=pVal_cmap,
norm=pVal_cnorm,
cmap=pVal_cmap.cmap,
norm=pVal_cmap.cnorm,
alpha=scatter_alpha,
**scatter_kwds)

Expand All @@ -1977,13 +1973,13 @@ def plot(self,
cbar_ax = fig.colorbar(h_ax,
ax=ax,
cax=cax,
boundaries=color_bounds,
boundaries=pVal_cmap.cnorm.boundaries,
ticks=[],
**cbar_kwds)
cbar_ax.ax.invert_yaxis()

if cbar_ticks is None:
cbar_ticks = pVal_clr_change
cbar_ticks = pVal_cmap.change_points
cbar_ax.set_ticks(cbar_ticks)

if cbar_ticklabels is None:
Expand Down Expand Up @@ -2538,3 +2534,246 @@ def _get_hp_from_kEff(self, kEff):
kEff = [kEff]

return interpolate(x_coords, y_coords, np.asarray(nn)).squeeze()

def plot_sweep(self,
fig=None,
gridspec=None,
box_widths=None,
box_positions=None,
box_notch=True,
box_bootstrap=100,
box_whiskers=(1, 99),
box_color='grey',
box_fliers=None,
box_props=None,
box_hl_color='grey',
box_hl_props=None,
values_2_highlight=None,
xLabel_idx=None,
xLabel=None,
xLabel_size=16,
xLim=None,
pVal_cmap=None,
fig_size=(12, 5),
fig_pad=0.4,
fig_ppad=0.01,
show_borders=False,
bot_wpad=0.0,
bot_hpad=0.0,
cax_ticklabels=None,
cax_width_frac=1.3,
cax_w2h_ratio=0.1):
"""Generates scatter plot of embedded data colored by EMBEDR p-value
Parameters
----------
"""

import matplotlib.gridspec as gs
import matplotlib.pyplot as plt

hp_array = np.sort(self.sweep_values)

if box_fliers is None:
box_fliers = {'marker': ".",
'markeredgecolor': box_color,
'markersize': 2,
'alpha': 0.5}

if box_props is None:
box_props = {'alpha': 0.5,
'color': box_color,
'fill': True}

if box_hl_props is None:
box_hl_props = box_props.copy()
box_hl_props.update({"alpha": 0.9, "color": box_hl_color})

if values_2_highlight is None:
values_2_highlight = []

box_patches = ['boxes', 'whiskers', 'fliers', 'caps', 'medians']

if fig is None:
fig = plt.figure(figsize=fig_size)

if gridspec is None:
gridspec = fig.add_gridspec(1, 1)

if pVal_cmap is None:
pVal_cmap = putl.CategoricalFadingCMap()

## Set up large axes
spine_alpha = 1 if show_borders else 0
bot_ax = fig.add_subplot(gridspec[0])
bot_ax = putl.make_border_axes(bot_ax, xticks=[], yticks=[],
spine_alpha=spine_alpha)

## Set up floating bottom gridspec
bot_gs = gs.GridSpec(nrows=1, ncols=1,
wspace=bot_wpad, hspace=bot_hpad)

ax = putl.make_border_axes(fig.add_subplot(bot_gs[0]),
yticklabels=[],
yticks=-np.sort(pVal_cmap.change_points),
spine_alpha=1)

putl.update_tight_bounds(fig, bot_gs, gridspec[0], w_pad=bot_wpad,
h_pad=bot_hpad, fig_pad=fig_pad)

hl_boxes = {}
hl_idx = []
for hpNo, hpVal in enumerate(hp_array):

if box_widths is not None:
try:
box_wid = box_widths[hpNo]
except TypeError as err:
box_wid = box_widths
else:
box_wid = 0.8

if box_positions is not None:
try:
box_pos = [box_positions[hpNo]]
except TypeError as err:
box_pos = [box_positions]
else:
box_pos = [hpNo]

if hpVal in values_2_highlight:
box_pps = box_hl_props.copy()
box_col = box_color
hl_idx.append(hpNo)
else:
box_pps = box_props.copy()
box_col = box_hl_color

box = ax.boxplot(np.log10(self.pValues[hpVal]),
widths=box_wid,
positions=box_pos,
notch=box_notch,
bootstrap=box_bootstrap,
patch_artist=True,
whis=box_whiskers,
boxprops=box_pps,
flierprops=box_fliers)

for item in box_patches:
plt.setp(box[item], color=box_col)

if hpVal in values_2_highlight:
hl_boxes[hpVal] = box['boxes'][0]

if xLabel_idx is None:
if values_2_highlight:
xLabel_idx = [0] + hl_idx + [hpNo]
else:
if len(hp_array) <= 5:
xLabel_idx = np.arange(len(hp_array))
else:
xLabel_idx = np.linspace(0, len(hp_array), 5)
xLabel_idx = human_round(xLabel_idx)
xLabel_idx = np.asarray(xLabel_idx).astype(int)

ax.set_xticks(xLabel_idx)
xticks = [f"{int(self.kEff[hp_array[idx]])}" for idx in xLabel_idx]
xticks = human_round(np.asarray(xticks).squeeze())
ax.grid(which='major', axis='x', alpha=0)
ax.set_xticklabels(xticks)

if xLim is None:
xLim = [-1, len(hp_array)]

ax.set_xlabel(r"$ k_{Eff}$", fontsize=xLabel_size, labelpad=0)
ax.set_xlim(*xLim)

# ax.set_yticks(-np.sort(pVal_cmap.change_points))
# ax.set_yticklabels([])

ax.set_ylim(-pVal_cmap.change_points.max(),
-pVal_cmap.change_points.min())

ax.tick_params(pad=-3)

## Update the figure again...
putl.update_tight_bounds(fig, bot_gs, gridspec[0], w_pad=bot_wpad,
h_pad=bot_hpad, fig_pad=fig_pad)

## Colorbar parameters
if cax_ticklabels is None:
cax_ticklabels = [f"{10.**(-cp):.1e}"
for cp in pVal_cmap.change_points]

inv_ax_trans = ax.transAxes.inverted()
fig_trans = fig.transFigure

## Convert from data to display
min_pVal = np.min([np.log10(self.pValues[hp].min())
for hp in self.sweep_values])
min_pVal = np.min([min_pVal, -pVal_cmap.change_points.max()])
max_pVal = np.max([np.log10(self.pValues[hp].max())
for hp in self.sweep_values])
max_pVal = np.min([max_pVal, -pVal_cmap.change_points.min()])
min_pVal_crds = ax.transData.transform([xLim[0], min_pVal])
max_pVal_crds = ax.transData.transform([xLim[0], max_pVal])

# print(f"min_pVal_crds: {min_pVal_crds}")
# print(f"max_pVal_crds: {max_pVal_crds}")

## Convert from display to figure coordinates
cFigX0, cFigY0 = fig.transFigure.inverted().transform(min_pVal_crds)
cFigX1, cFigY1 = fig.transFigure.inverted().transform(max_pVal_crds)

# print(f"cFig0: {cFigX0:.4f}, {cFigY0:.4f}")
# print(f"cFig1: {cFigX1:.4f}, {cFigY1:.4f}")

cFig_height = np.abs(cFigY1 - cFigY0)
cFig_width = cax_w2h_ratio * cFig_height

# print(f"The color bar will be {cFig_width:.4f} x {cFig_height:.4f}")

cAxX0, cAxY0 = cFigX0 - cax_width_frac * cFig_width, cFigY0
cAxX1, cAxY1 = cAxX0 + cFig_width, cFigY0 + cFig_height

## Convert from Figure back into Axes
[cAxX0,
cAxY0] = inv_ax_trans.transform(fig_trans.transform([cAxX0, cAxY0]))
[cAxX1,
cAxY1] = inv_ax_trans.transform(fig_trans.transform([cAxX1, cAxY1]))

# print(f"cAx0: {cAxX0:.4f}, {cAxY0:.4f}")
# print(f"cAx1: {cAxX1:.4f}, {cAxY1:.4f}")

cAx_height = np.abs(cAxY1 - cAxY0)
cAx_width = np.abs(cAxX1 - cAxX0)

# print(f"The color bar will be {cAx_width:.4f} x {cAx_height:.4f}")

caxIns = ax.inset_axes([cAxX0, cAxY0, cAx_width, cAx_height])
caxIns = putl.make_border_axes(caxIns, spine_alpha=0)

hax = plt.scatter([], [], c=[], s=[], cmap=pVal_cmap.cmap,
norm=pVal_cmap.cnorm)
cAx = fig.colorbar(hax, cax=caxIns, ticks=[],
boundaries=pVal_cmap.cnorm.boundaries)
cAx.ax.invert_yaxis()

cAx.set_ticks(pVal_cmap.change_points)
cAx.set_ticklabels(cax_ticklabels)
cAx.ax.tick_params(length=0)
cAx.ax.yaxis.set_ticks_position('left')

cAx.ax.set_ylabel(r"EMBEDR $p$-Value",
fontsize=xLabel_size,
labelpad=2)
cAx.ax.yaxis.set_label_position('left')

## Update the figure again...
putl.update_tight_bounds(fig, bot_gs, gridspec[0], w_pad=bot_wpad,
h_pad=bot_hpad, fig_pad=fig_pad)

return ax



3 changes: 1 addition & 2 deletions EMBEDR/human_round.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,7 @@ def human_round(x,
Options are 'up', 'down', and 'none'.
"""

if not is_iterable(x):
x = np.asarray([x])
x = np.asarray([x]).squeeze().astype(float)

if not inplace:
x = x.copy()
Expand Down
Loading

0 comments on commit 385c37b

Please sign in to comment.