Skip to content

Commit a208cb9

Browse files
committed
Version 1.0.1:
- In the network plot: added the option to define a custom colormap when using metadata with categorical features.
1 parent 2eadfdd commit a208cb9

File tree

4 files changed

+69
-35
lines changed

4 files changed

+69
-35
lines changed

SynTrackerVis_app/config.py

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -92,18 +92,19 @@
9292
'spring', 'summer', 'autumn', 'winter', 'cool', 'Wistia']
9393

9494
categorical_colormap_dict = {
95-
'cet_glasbey': cc.glasbey,
96-
'cet_glasbey_light': cc.glasbey_light,
97-
'cet_glasbey_category10': bp.Category10[10],
95+
'Glasbey': cc.glasbey,
96+
'Glasbey_light': cc.glasbey_light,
97+
'Glasbey_category10': bp.Category10[10],
9898
'Set1': bp.Set1[9],
99-
'Set3': bp.Set3[12]
99+
'Set3': bp.Set3[12],
100+
'Define custom colormap': ['#000000']
100101
}
101102

102103
continuous_colormap_dict = {
103-
'cet_rainbow4': cc.m_rainbow4,
104-
'cet_isolum': cc.isolum,
105-
'plasma': bp.Plasma256,
106-
'viridis': bp.Viridis256,
104+
'Rainbow4': cc.m_rainbow4,
105+
'Isolum': cc.isolum,
106+
'Plasma': bp.Plasma256,
107+
'Viridis': bp.Viridis256,
107108
'Blues': bp.Blues256,
108109
'Reds': bp.Reds256,
109110
'Greens': bp.Greens256,

SynTrackerVis_app/manual.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,11 @@ The variety of colormaps available for selection changes accordingly and a color
172172
Note that only features which numerical values can be checked as continuous.
173173
- **Select colormap for nodes:** Select a colormap from the drop-down menu to color the nodes by the different groups of the selected metadata feature.
174174
A different set of colormaps is provided for categorical data and for continuous data.
175+
- **Define custom colormap:** For categorical features, it is also possible to define a custom list of colors for the different groups.
176+
This option becomes active when selecting the 'Define custom colormap' option from the colormaps drop-down menu.
177+
A list of colors, separated by commas, can be entered to the text-input widget.
178+
The colors can be provided as standard names (like: red, blue) or Hex-RGB values (like: #FF0000).
179+
A detailed guide for color notations: https://www.w3.org/TR/css-color-4/#named-colors .
175180
- **Color edges by feature (same/different):** Checking this option enables to select a feature, by which the edges (connections)
176181
are divided into two categories and can be colored differently.
177182
One category is the connections between samples that belong to the same group and the other is the connections between samples that belong to a different group (of the selected feature).

SynTrackerVis_app/plots_single_genome.py

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import time
2+
import re
23
import numpy as np
34
import pandas as pd
45
import networkx as nx
@@ -129,7 +130,7 @@ def create_clustermap(matrix, cmap):
129130
return clustermap.figure
130131

131132

132-
def cretae_network_plot(network, is_metadata, nodes_feature, is_continuous, cmap, node_color, edge_color,
133+
def cretae_network_plot(network, is_metadata, nodes_feature, is_continuous, cmap, custom_cmap, node_color, edge_color,
133134
is_edge_colorby, edges_feature, within_edge_color, between_edge_color, iterations, pos_dict,
134135
show_labels, metadata_dict):
135136
iter_num = int(iterations)
@@ -193,15 +194,27 @@ def cretae_network_plot(network, is_metadata, nodes_feature, is_continuous, cmap
193194
print("Categorical feature")
194195

195196
# Prepare the colors mapping for the legend
196-
unique_groups = list(set([str(network.nodes[node][nodes_feature]) for node in network.nodes()]))
197+
unique_groups = sorted(list(set([str(network.nodes[node][nodes_feature]) for node in network.nodes()])))
197198
groups_num = len(unique_groups)
198199
# Move the 'nan' group (if any) to the end of the list
199200
if 'nan' in unique_groups:
200201
unique_groups.remove('nan')
201202
unique_groups.append('nan')
202203
print(unique_groups)
204+
203205
cmap_length = len(cmap)
204206
print("Cmap length = " + str(cmap_length))
207+
208+
# If the user defined a custom cmap - process it and turn it into a cmap
209+
if cmap_length == 1:
210+
custom_colors_list = custom_cmap
211+
#cmap = custom_colors_list.split(',')
212+
cmap = re.split(r'\s*,\s*', custom_colors_list)
213+
cmap_length = len(cmap)
214+
print("Custom cmap:")
215+
print(cmap)
216+
print("custom cmap length: " + str(cmap_length))
217+
205218
group_to_color = {group: cmap[i % cmap_length] for i, group in enumerate(unique_groups)}
206219
colors = [group_to_color[str(network.nodes[node][nodes_feature])] for node in network.nodes()]
207220

@@ -256,9 +269,9 @@ def cretae_network_plot(network, is_metadata, nodes_feature, is_continuous, cmap
256269
return hv_layout
257270

258271

259-
def cretae_network_plot_matplotlib(network, is_metadata, nodes_feature, is_continuous, cmap, node_color, edge_color,
260-
is_edge_colorby, edges_feature, within_edge_color, between_edge_color, iterations,
261-
pos_dict, show_labels, metadata_dict):
272+
def cretae_network_plot_matplotlib(network, is_metadata, nodes_feature, is_continuous, cmap, custom_cmap, node_color,
273+
edge_color, is_edge_colorby, edges_feature, within_edge_color, between_edge_color,
274+
iterations, pos_dict, show_labels, metadata_dict):
262275
iter_num = int(iterations)
263276
print("\nIn cretae_network_plot_matplotlib. Iterations number = " + str(iter_num))
264277
print("cmap: " + str(cmap))
@@ -340,7 +353,7 @@ def cretae_network_plot_matplotlib(network, is_metadata, nodes_feature, is_conti
340353
# Feature is categorical
341354
else:
342355
# Prepare the colors mapping for the matplotlib plot
343-
unique_groups = list(set([str(network.nodes[node][nodes_feature]) for node in network.nodes()]))
356+
unique_groups = sorted(list(set([str(network.nodes[node][nodes_feature]) for node in network.nodes()])))
344357
groups_num = len(unique_groups)
345358
# Move the 'nan' group (if any) to the end of the list
346359
if 'nan' in unique_groups:

SynTrackerVis_app/syntracker_vis_app.py

Lines changed: 36 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -47,22 +47,15 @@ def change_collapse_state(selection_val):
4747
return False
4848

4949

50-
def change_continuous_state(chkbox_state):
51-
if chkbox_state:
52-
return config.continuous_colormap_dict
53-
else:
54-
return config.categorical_colormap_dict
55-
56-
57-
def change_continuous_state_for_value(chkbox_state):
58-
if chkbox_state:
59-
return config.continuous_colormap_dict['cet_rainbow4']
50+
def change_disabled_state_threshold(value):
51+
if value == 'Define another threshold':
52+
return False
6053
else:
61-
return config.categorical_colormap_dict['cet_glasbey']
54+
return True
6255

6356

64-
def change_disabled_state_threshold(value):
65-
if value == 'Define another threshold':
57+
def change_disabled_state_custom_colormap(value):
58+
if value == config.categorical_colormap_dict['Define custom colormap']:
6659
return False
6760
else:
6861
return True
@@ -152,6 +145,7 @@ def __init__(self):
152145
self.feature_select_watcher = ""
153146
self.continuous_watcher = ""
154147
self.colormap_watcher = ""
148+
self.custom_colormap_watcher = ""
155149
self.nodes_colorby_watcher = ""
156150
self.visited_multi_genome_tab = 0
157151

@@ -332,7 +326,7 @@ def __init__(self):
332326
self.use_metadata_network = pn.widgets.Checkbox(name='Use metadata for coloring', value=False)
333327
self.color_edges_by_feature = pn.widgets.Checkbox(name='Color edges by feature (same/different)', value=False)
334328
self.metadata_colorby_card = pn.Card(title='Set the coloring by metadata', header_background="#ffffff",
335-
styles={'background': "#ffffff", 'margin': "10px", 'width': "300px"},
329+
styles={'background': "#ffffff", 'margin': "10px", 'width': "335px"},
336330
hide_header=True, collapsed=pn.bind(change_disabled_state_inverse,
337331
chkbox_state=self.use_metadata_network,
338332
watch=True))
@@ -344,11 +338,18 @@ def __init__(self):
344338
disabled=pn.bind(change_disabled_state_straight,
345339
chkbox_state=self.use_metadata_network,
346340
watch=True))
347-
self.nodes_color_by = pn.widgets.Select(options=['Select feature'], name="Color nodes by:", width=100)
341+
self.nodes_color_by = pn.widgets.Select(options=['Select feature'], name="Color nodes by:", width=130)
348342
self.is_continuous = pn.widgets.Checkbox(name='Continuous feature', value=False)
349343
self.nodes_colormap = pn.widgets.ColorMap(name="Select colormap for nodes:",
350344
options=config.categorical_colormap_dict,
351-
value=config.categorical_colormap_dict['cet_glasbey'])
345+
value=config.categorical_colormap_dict['Glasbey'])
346+
self.custom_colormap_input = pn.widgets.TextInput(name='Custom colormap: enter a list of colors separated by '
347+
'comma:',
348+
placeholder='color1, color2, color3, etc...',
349+
disabled=pn.bind(change_disabled_state_custom_colormap,
350+
value=self.nodes_colormap,
351+
watch=True)
352+
)
352353
self.edges_color_by = pn.widgets.Select(options=['Select feature'],
353354
name="Color edges by:", width=100,
354355
disabled=pn.bind(change_disabled_state_inverse,
@@ -532,6 +533,7 @@ def init_parameters(self):
532533
self.nodes_color_by.param.unwatch(self.nodes_colorby_watcher)
533534
self.is_continuous.param.unwatch(self.continuous_watcher)
534535
self.nodes_colormap.param.unwatch(self.colormap_watcher)
536+
self.custom_colormap_input.param.unwatch(self.custom_colormap_watcher)
535537
self.box_plot_feature_select.param.unwatch(self.feature_select_watcher)
536538
self.genomes_select.param.unwatch(self.genomes_select_watcher)
537539
self.genomes_sort_select.param.unwatch(self.genomes_sort_select_watcher)
@@ -1057,11 +1059,12 @@ def create_single_genome_plots_by_APSS(self, event):
10571059
if self.is_metadata:
10581060
self.is_continuous.param.unwatch(self.continuous_watcher)
10591061
self.nodes_colormap.param.unwatch(self.colormap_watcher)
1062+
self.custom_colormap_input.param.unwatch(self.custom_colormap_watcher)
10601063
self.nodes_color_by.param.unwatch(self.nodes_colorby_watcher)
10611064
self.network_threshold_input.value = config.APSS_connections_threshold_default
10621065
self.is_continuous.value = False
10631066
self.nodes_colormap.options = config.categorical_colormap_dict
1064-
self.nodes_colormap.value = config.categorical_colormap_dict['cet_glasbey']
1067+
self.nodes_colormap.value = config.categorical_colormap_dict['Glasbey']
10651068

10661069
# Check if the requested genome and size have already been calculated. If so, fetch the specific dataframe
10671070
if self.calculated_APSS_genome_size_dict[self.sampling_size]:
@@ -1408,18 +1411,22 @@ def change_continuous_state(self, event):
14081411
# Feature is indeed really continuous
14091412
else:
14101413
self.nodes_colormap.options = config.continuous_colormap_dict
1411-
self.nodes_colormap.value = config.continuous_colormap_dict['cet_rainbow4']
1414+
self.nodes_colormap.value = config.continuous_colormap_dict['Rainbow4']
14121415

14131416
# Categorical feature
14141417
else:
14151418
#print("\nIn change_continuous_state. Categorical feature")
14161419
self.nodes_colormap.options = config.categorical_colormap_dict
1417-
self.nodes_colormap.value = config.categorical_colormap_dict['cet_glasbey']
1420+
self.nodes_colormap.value = config.categorical_colormap_dict['Glasbey']
14181421

14191422
def change_colormap(self, event):
14201423
#print("\nIn change_colormap. Continuous state = " + str(self.is_continuous.value))
14211424
self.update_network_plot()
14221425

1426+
def get_custom_colormap(self, event):
1427+
#print("\nIn change_colormap. Continuous state = " + str(self.is_continuous.value))
1428+
self.update_network_plot()
1429+
14231430
def set_not_continuous(self, event):
14241431
#print("\nIn set_not_continuous")
14251432
self.is_continuous.value = False
@@ -1438,6 +1445,7 @@ def create_network_pane(self, selected_genome_and_size_avg_df):
14381445
self.network_between_color)
14391446
metadata_coloring_col = pn.Column(nodes_color_by_row,
14401447
self.nodes_colormap,
1448+
self.custom_colormap_input,
14411449
pn.Spacer(height=10),
14421450
self.color_edges_by_feature,
14431451
edges_color_by_row,
@@ -1580,6 +1588,8 @@ def create_network_pane(self, selected_genome_and_size_avg_df):
15801588
onlychanged=True)
15811589
self.colormap_watcher = self.nodes_colormap.param.watch(self.change_colormap, 'value',
15821590
onlychanged=True)
1591+
self.custom_colormap_watcher = self.custom_colormap_input.param.watch(self.get_custom_colormap,
1592+
'value', onlychanged=True)
15831593

15841594
# Insert the features information as nodes attributes
15851595
for node in self.nodes_list:
@@ -1602,7 +1612,9 @@ def create_network_pane(self, selected_genome_and_size_avg_df):
16021612
is_metadata=self.use_metadata_network,
16031613
nodes_feature=self.nodes_color_by.value,
16041614
is_continuous=self.is_continuous.value,
1605-
cmap=self.nodes_colormap.value, node_color=self.network_node_color,
1615+
cmap=self.nodes_colormap.value,
1616+
custom_cmap=self.custom_colormap_input.value,
1617+
node_color=self.network_node_color,
16061618
edge_color=self.network_edge_color,
16071619
is_edge_colorby=self.color_edges_by_feature,
16081620
edges_feature=self.edges_color_by,
@@ -1654,7 +1666,9 @@ def download_network(self, event):
16541666
is_metadata=self.use_metadata_network,
16551667
nodes_feature=self.nodes_color_by.value,
16561668
is_continuous=self.is_continuous.value,
1657-
cmap=self.nodes_colormap.value_name, node_color=self.network_node_color,
1669+
cmap=self.nodes_colormap.value_name,
1670+
custom_cmap=self.custom_colormap_input.value,
1671+
node_color=self.network_node_color,
16581672
edge_color=self.network_edge_color,
16591673
is_edge_colorby=self.color_edges_by_feature,
16601674
edges_feature=self.edges_color_by,
@@ -1785,6 +1799,7 @@ def update_network_plot(self):
17851799
self.network_plot_hv = pn.bind(ps.cretae_network_plot, network=self.network,
17861800
is_metadata=self.use_metadata_network, nodes_feature=self.nodes_color_by.value,
17871801
is_continuous=self.is_continuous.value, cmap=self.nodes_colormap.value,
1802+
custom_cmap=self.custom_colormap_input.value,
17881803
node_color=self.network_node_color, edge_color=self.network_edge_color,
17891804
is_edge_colorby=self.color_edges_by_feature, edges_feature=self.edges_color_by,
17901805
within_edge_color=self.network_within_color,

0 commit comments

Comments
 (0)