Skip to content

Commit a55c297

Browse files
minor changes in plotting function for convenience
1 parent 29a4fca commit a55c297

1 file changed

Lines changed: 55 additions & 20 deletions

File tree

src/netmap/downstream/plotting.py

Lines changed: 55 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
from mpl_toolkits.axes_grid1.inset_locator import inset_axes
1414

1515

16-
def rank_regulon_groups_dotplot(grn_adata_filtered, adata_regl, original_cluster_column = 'leiden', new_cluster_column = 'leiden_remap', n_genes=10, key="wilcoxon", cmap='bwr', figsize=(25, 2), values_to_plot="scores", return_fig = True):
16+
def rank_regulon_groups_dotplot(grn_adata_filtered, adata_regl, original_cluster_column = 'leiden', new_cluster_column = 'leiden_remap', n_genes=10, key="wilcoxon", cmap='bwr', figsize=(25, 2), values_to_plot="scores", return_fig = True, var_group_rotation=0):
1717
"""_summary_
1818
1919
Function will throw and error if original cluster column and new cluster are not the same.
@@ -56,7 +56,8 @@ def rank_regulon_groups_dotplot(grn_adata_filtered, adata_regl, original_cluster
5656
fractions.index = [x.replace('_nonzero', '') for x in fractions.index]
5757

5858
# return fig needs to be true: get plot, modify sizes, then plot or return
59-
pp = sc.pl.rank_genes_groups_dotplot(adata_regl, n_genes=n_genes, key=key, groupby=new_cluster_column, cmap=cmap, figsize=figsize, values_to_plot=values_to_plot, return_fig = True)
59+
pp = sc.pl.rank_genes_groups_dotplot(adata_regl, n_genes=n_genes, key=key, groupby=new_cluster_column, cmap=cmap, figsize=figsize, values_to_plot=values_to_plot, return_fig=True, var_group_rotation =var_group_rotation)
60+
print(pp)
6061
fractions = fractions.reindex(list(pp.dot_size_df.index))
6162

6263
pp.dot_size_df = fractions.loc[:, pp.dot_color_df.columns]
@@ -88,42 +89,76 @@ def get_grn_from_regulon(regulon_df, full_name, top_n=20):
8889
return nx.from_pandas_edgelist(subset, 'source', 'target', create_using=nx.DiGraph())
8990

9091
def draw_inset_graph(parent_ax, G, orientation='x'):
91-
"""Handles the geometry of the marginal GRN plots."""
92-
bbox = (0.0, -0.45, 1.0, 0.3) if orientation == 'x' else (-0.45, 0.0, 0.3, 1.0)
92+
# Pushing the bbox further (to -0.5) to avoid any overlap with the axis frame
93+
if orientation == 'x':
94+
bbox = (0.0, -0.52, 1.0, 0.35)
95+
else:
96+
bbox = (-0.52, 0.0, 0.35, 1.0)
97+
9398
ax_ins = inset_axes(parent_ax, width="100%", height="100%", loc='center',
94-
bbox_to_anchor=bbox, bbox_transform=parent_ax.transAxes)
99+
bbox_to_anchor=bbox, bbox_transform=parent_ax.transAxes, borderpad=0)
95100

96-
pos = nx.spring_layout(G, k=1.5, seed=42)
97-
nx.draw_networkx(G, pos, ax=ax_ins, node_size=200, node_color='#a8dadc',
98-
edge_color='#457b9d', alpha=0.7, font_size=7, font_weight='bold')
101+
if len(G) > 0:
102+
pos = nx.kamada_kawai_layout(G)
103+
104+
# Logic for 2-node graphs to keep edges from looking like infinite lines
105+
if len(G) <= 3:
106+
ax_ins.set_xlim(-2.5, 2.5)
107+
ax_ins.set_ylim(-2.5, 2.5)
108+
else:
109+
x_values, y_values = zip(*pos.values())
110+
x_r, y_r = max(x_values) - min(x_values), max(y_values) - min(y_values)
111+
ax_ins.set_xlim(min(x_values) - x_r*0.4, max(x_values) + x_r*0.4)
112+
ax_ins.set_ylim(min(y_values) - y_r*0.4, max(y_values) + y_r*0.4)
113+
114+
nx.draw_networkx_edges(G, pos, ax=ax_ins, edge_color='#bdc3c7', alpha=0.4, width=0.8)
115+
nx.draw_networkx_nodes(G, pos, ax=ax_ins, node_size=100, node_color='#f8f9fa',
116+
edgecolors='#34495e', linewidths=0.5)
117+
nx.draw_networkx_labels(G, pos, ax=ax_ins, font_size=7, font_weight='bold', clip_on=False)
118+
99119
ax_ins.axis('off')
100120

101-
def plot_regulon_comparison(adata, regulon_table, regulons, cluster_key='leiden_remap'):
102-
"""
103-
The 'One-Liner' function.
104-
Pass it the adata, the big regulon table, and the two strings.
105-
"""
121+
def plot_regulon_comparison(adata, regulon_table, regulons, cluster_key='leiden_remap', palette=None, show_legend=True):
106122
# 1. Prepare Scatter Data
107123
df = pd.DataFrame(adata[:, regulons].X.copy(), columns=regulons)
108124
df['group'] = adata.obs[cluster_key].values
109125

110-
# 2. Build Graphs automatically from the names
126+
# 2. Build Graphs
111127
G_x = get_grn_from_regulon(regulon_table, regulons[0])
112128
G_y = get_grn_from_regulon(regulon_table, regulons[1])
113129

114130
# 3. Plotting
115-
fig, ax = plt.subplots(figsize=(9, 9))
116-
plt.subplots_adjust(left=0.25, bottom=0.25)
131+
fig, ax = plt.subplots(figsize=(4, 4))
132+
133+
# Increase margins significantly to accommodate external GRNs and titles
134+
plt.subplots_adjust(top=0.82, right=0.82, left=0.18, bottom=0.18)
117135

118-
sns.scatterplot(data=df, x=regulons[0], y=regulons[1], hue='group', ax=ax, s=20, alpha=0.5)
136+
sns.scatterplot(
137+
data=df, x=regulons[0], y=regulons[1], hue='group',
138+
palette=palette, ax=ax, s=20, alpha=0.5, legend=show_legend
139+
)
119140

141+
# Draw Insets with extra clearance
120142
draw_inset_graph(ax, G_x, 'x')
121143
draw_inset_graph(ax, G_y, 'y')
122144

123-
# Clean up aesthetics
124-
sns.despine(ax=ax)
125-
ax.legend(title='Cluster', bbox_to_anchor=(1.05, 1), loc='upper left')
145+
# 4. Move Labels and Shrink Ticks
146+
ax.xaxis.set_label_position('top')
147+
ax.yaxis.set_label_position('right')
148+
149+
# Shrink the numbers on the axes
150+
ax.tick_params(axis='both', which='major', labelsize=7)
126151

152+
# 5. Legend Styling
153+
if show_legend:
154+
ax.legend(
155+
title=cluster_key, bbox_to_anchor=(1.2, 1), loc='upper left',
156+
fontsize=6, title_fontsize=7, frameon=False
157+
)
158+
elif ax.get_legend():
159+
ax.get_legend().remove()
160+
161+
sns.despine(ax=ax)
127162
return fig, ax
128163

129164

0 commit comments

Comments
 (0)