diff --git a/Docs/ChangeLog.md b/Docs/ChangeLog.md
index 9ffc4f6..9fdf39e 100644
--- a/Docs/ChangeLog.md
+++ b/Docs/ChangeLog.md
@@ -1,3 +1,10 @@
+# Version: 1.107.2
+## Date: 2024-06-16
+### Changes:
+- New: Added an option in 'Help' menu to open the online Tutorial page.
+- Change: Co-expression Network plot: Use the corelation value as the weight of the edge, and improve the layout of the plot.
+- Fix: Fixed the bug of when plot the Taxa-Functions Network, the shape setting was not work withotu focus list.
+
# Version: 1.107.1
## Date: 2024-06-16
### Changes:
diff --git a/Docs/MetaX_Cookbook.assets/settings_page2.png b/Docs/MetaX_Cookbook.assets/settings_page2.png
index abfd9b8..2564529 100644
Binary files a/Docs/MetaX_Cookbook.assets/settings_page2.png and b/Docs/MetaX_Cookbook.assets/settings_page2.png differ
diff --git a/Docs/MetaX_Cookbook.assets/tf_link_net_2.png b/Docs/MetaX_Cookbook.assets/tf_link_net_2.png
new file mode 100644
index 0000000..c51288c
Binary files /dev/null and b/Docs/MetaX_Cookbook.assets/tf_link_net_2.png differ
diff --git a/README.md b/README.md
index fea6b74..ea3c64e 100644
--- a/README.md
+++ b/README.md
@@ -9,7 +9,15 @@ MetaX also features statistical modules and plotting tools for ana
## Taxa-Functions Linkage
Linking Taxa and Functions in different levels of the hierarchy, and different functional categories. e.g., **Species-KO**, **Genus-CAZy**, **Phylum-EC**, etc.
-![OTF](./Docs/MetaX_Cookbook.assets/tf_link_net.png)
+- ![OTF](./Docs/MetaX_Cookbook.assets/tf_link_net.png)
+
+
+
+e.g. The **KEGG Pathways** linked to ***Roseburia hominis***
+
+- ![tf_link_net_2](./Docs/MetaX_Cookbook.assets/tf_link_net_2.png)
+
+
## Download
### `Desktop Version(Recommended)`:
diff --git a/utils/GUI.py b/utils/GUI.py
index e30d897..7b8bdf9 100644
--- a/utils/GUI.py
+++ b/utils/GUI.py
@@ -163,8 +163,8 @@ def __init__(self, MainWindow):
self.tf_link_net_params_dict = {'taxa_shape': 'circle', 'func_shape': 'rect',
'taxa_color': '#374E55','taxa_focus_color': '#6A6599',
'func_color': '#DF8F44', 'func_focus_color': '#B24745',
- 'line_opacity': 0.5, 'line_width': 2, 'line_curve': 0.1,
- 'line_color': '#9aa7b1', 'repulsion': 500
+ 'line_opacity': 0.5, 'line_width': 2, 'line_curve': 0,
+ 'line_color': '#9aa7b1', 'repulsion': 500, 'font_weight': 'bold'
}
@@ -182,12 +182,14 @@ def __init__(self, MainWindow):
self.actionAny_Table_Mode.setIcon(qta.icon('mdi.table'))
self.actionCheck_Update.setIcon(qta.icon('mdi.update'))
self.actionSettings.setIcon(qta.icon('mdi.cog'))
+ self.actionTutorial.setIcon(qta.icon('mdi6.book-open-page-variant-outline'))
# set menu bar click event
self.actionTaxaFuncAnalyzer.triggered.connect(self.swith_stack_page_analyzer)
self.actionPeptide_to_TaxaFunc.triggered.connect(self.swith_stack_page_pep2taxafunc)
self.actionDatabase_Builder.triggered.connect(self.swith_stack_page_dbuilder)
self.actionDatabase_Update.triggered.connect(self.swith_stack_page_db_update)
self.actionAbout.triggered.connect(self.show_about)
+ self.actionTutorial.triggered.connect(self.open_tutorial)
self.actionRestore_Last_TaxaFunc.triggered.connect(lambda: self.run_restore_taxafunnc_obj_from_file(last=True))
self.actionRestore_From.triggered.connect(self.run_restore_taxafunnc_obj_from_file)
self.actionSave_As.triggered.connect(lambda:self.save_metax_obj_to_file(save_path=None, no_message=False))
@@ -1381,7 +1383,15 @@ def check_update(self, show_message=False, manual_check_trigger=True):
updater = Updater(MetaXGUI=self, version=__version__, splash=splash, show_message=show_message, branch=self.update_branch)
updater.check_update(show_message=show_message)
+ def open_tutorial(self):
+ # use default browser to open the tutorial link
+ from PyQt5.QtGui import QDesktopServices
+ from PyQt5.QtCore import QUrl
+ url = QUrl("https://byemaxx.github.io/MetaX/")
+ QDesktopServices.openUrl(url)
+
+
def show_about(self):
dialog = QDialog(self.MainWindow)
@@ -1406,6 +1416,7 @@ def show_about(self):
Aditional Information
For more information, please visit:
GitHub: The MetaX Project
+ Tutorial: MetaX Tutorial
iMeta: iMetaWiki Page
'''
@@ -4836,6 +4847,7 @@ def plot_co_expr_network(self):
show_labels=show_labels,
rename_taxa=rename_taxa,
font_size=font_size,
+ **self.tf_link_net_params_dict
).plot_co_expression_network(df_type= df_type, corr_method=corr_method,
corr_threshold=corr_threshold, sample_list=sample_list, width=width, height=height, focus_list=focus_list, plot_list_only=plot_list_only)
self.save_and_show_js_plot(pic, 'co-expression network')
diff --git a/utils/MetaX_GUI/MainWindow.ui b/utils/MetaX_GUI/MainWindow.ui
index d684bb0..44f8edc 100644
--- a/utils/MetaX_GUI/MainWindow.ui
+++ b/utils/MetaX_GUI/MainWindow.ui
@@ -7382,8 +7382,8 @@
0
0
- 981
- 332
+ 313
+ 41
@@ -8038,6 +8038,7 @@
+
comboBox_taxa_level_to_stast
diff --git a/utils/MetaX_GUI/Setting.ui b/utils/MetaX_GUI/Setting.ui
index 7641ec1..3900e7e 100644
--- a/utils/MetaX_GUI/Setting.ui
+++ b/utils/MetaX_GUI/Setting.ui
@@ -24,8 +24,8 @@
0
0
- 748
- 367
+ 246
+ 37
@@ -113,7 +113,7 @@
0.100000000000000
- 0.100000000000000
+ 0.000000000000000
@@ -335,7 +335,7 @@
-
- 10000
+ 100000
10
@@ -345,6 +345,37 @@
+ -
+
+
+ Font Weight
+
+
+
+ -
+
+
-
+
+ bold
+
+
+ -
+
+ normal
+
+
+ -
+
+ bolder
+
+
+ -
+
+ lighter
+
+
+
+
-
diff --git a/utils/MetaX_GUI/Settings.py b/utils/MetaX_GUI/Settings.py
index 7d31cbf..e1fde9c 100644
--- a/utils/MetaX_GUI/Settings.py
+++ b/utils/MetaX_GUI/Settings.py
@@ -50,7 +50,7 @@ def __init__(self, parent=None, update_branch="main", auto_check_update=True):
self.ui.doubleSpinBox_tf_link_net_line_curve.valueChanged.connect(self.handle_tf_link_network_changed)
self.ui.lineEdit_tf_link_net_line_color.textChanged.connect(self.handle_tf_link_network_changed)
self.ui.spinBox_tf_link_net_repulsion.valueChanged.connect(self.handle_tf_link_network_changed)
-
+ self.ui.comboBox_tf_link_net_font_weight.currentTextChanged.connect(self.handle_tf_link_network_changed)
def init_ui(self, update_mode, auto_check_update):
if update_mode == "main":
@@ -88,7 +88,8 @@ def handle_tf_link_network_changed(self):
"line_curve": self.ui.doubleSpinBox_tf_link_net_line_curve.value(),
"line_color": self.ui.lineEdit_tf_link_net_line_color.text(),
- 'repulsion': self.ui.spinBox_tf_link_net_repulsion.value()
+ 'repulsion': self.ui.spinBox_tf_link_net_repulsion.value(),
+ 'font_weight': self.ui.comboBox_tf_link_net_font_weight.currentText()
}
self.tf_link_net_params_dict_changed.emit(network_params_dict)
diff --git a/utils/MetaX_GUI/Ui_MainWindow.py b/utils/MetaX_GUI/Ui_MainWindow.py
index 24af019..cb04641 100644
--- a/utils/MetaX_GUI/Ui_MainWindow.py
+++ b/utils/MetaX_GUI/Ui_MainWindow.py
@@ -3884,7 +3884,7 @@ def setupUi(self, metaX_main):
self.toolBox_metalab_res_anno = QtWidgets.QToolBox(self.tab_18)
self.toolBox_metalab_res_anno.setObjectName("toolBox_metalab_res_anno")
self.page_3 = QtWidgets.QWidget()
- self.page_3.setGeometry(QtCore.QRect(0, 0, 981, 332))
+ self.page_3.setGeometry(QtCore.QRect(0, 0, 313, 41))
self.page_3.setObjectName("page_3")
self.gridLayout_45 = QtWidgets.QGridLayout(self.page_3)
self.gridLayout_45.setObjectName("gridLayout_45")
@@ -4243,12 +4243,15 @@ def setupUi(self, metaX_main):
self.actionAny_Table_Mode.setObjectName("actionAny_Table_Mode")
self.actionSettings = QtWidgets.QAction(metaX_main)
self.actionSettings.setObjectName("actionSettings")
+ self.actionTutorial = QtWidgets.QAction(metaX_main)
+ self.actionTutorial.setObjectName("actionTutorial")
self.menuTools.addAction(self.actionTaxaFuncAnalyzer)
self.menuTools.addAction(self.actionPeptide_to_TaxaFunc)
self.menuTools.addAction(self.actionDatabase_Builder)
self.menuTools.addAction(self.actionDatabase_Update)
self.menuHelp.addAction(self.actionAbout)
self.menuHelp.addAction(self.actionCheck_Update)
+ self.menuHelp.addAction(self.actionTutorial)
self.menuOthers.addAction(self.actionRestore_Last_TaxaFunc)
self.menuOthers.addAction(self.actionRestore_From)
self.menuOthers.addAction(self.actionSave_As)
@@ -4963,3 +4966,4 @@ def retranslateUi(self, metaX_main):
self.actionRestore_From.setText(_translate("metaX_main", "Restore From.."))
self.actionAny_Table_Mode.setText(_translate("metaX_main", "Any Table Mode"))
self.actionSettings.setText(_translate("metaX_main", "Settings"))
+ self.actionTutorial.setText(_translate("metaX_main", "Tutorial"))
diff --git a/utils/MetaX_GUI/Ui_Setting.py b/utils/MetaX_GUI/Ui_Setting.py
index 296a14b..b235db8 100644
--- a/utils/MetaX_GUI/Ui_Setting.py
+++ b/utils/MetaX_GUI/Ui_Setting.py
@@ -20,7 +20,7 @@ def setupUi(self, Settings):
self.toolBox = QtWidgets.QToolBox(Settings)
self.toolBox.setObjectName("toolBox")
self.page = QtWidgets.QWidget()
- self.page.setGeometry(QtCore.QRect(0, 0, 748, 367))
+ self.page.setGeometry(QtCore.QRect(0, 0, 246, 37))
self.page.setObjectName("page")
self.gridLayout_3 = QtWidgets.QGridLayout(self.page)
self.gridLayout_3.setObjectName("gridLayout_3")
@@ -59,7 +59,7 @@ def setupUi(self, Settings):
self.doubleSpinBox_tf_link_net_line_curve.setDecimals(1)
self.doubleSpinBox_tf_link_net_line_curve.setMaximum(1.0)
self.doubleSpinBox_tf_link_net_line_curve.setSingleStep(0.1)
- self.doubleSpinBox_tf_link_net_line_curve.setProperty("value", 0.1)
+ self.doubleSpinBox_tf_link_net_line_curve.setProperty("value", 0.0)
self.doubleSpinBox_tf_link_net_line_curve.setObjectName("doubleSpinBox_tf_link_net_line_curve")
self.gridLayout_6.addWidget(self.doubleSpinBox_tf_link_net_line_curve, 2, 3, 1, 1)
self.comboBox_tf_link_net_taxa_sahpe = QtWidgets.QComboBox(self.page_2)
@@ -142,11 +142,21 @@ def setupUi(self, Settings):
self.label_15.setObjectName("label_15")
self.gridLayout_6.addWidget(self.label_15, 2, 4, 1, 1)
self.spinBox_tf_link_net_repulsion = QtWidgets.QSpinBox(self.page_2)
- self.spinBox_tf_link_net_repulsion.setMaximum(10000)
+ self.spinBox_tf_link_net_repulsion.setMaximum(100000)
self.spinBox_tf_link_net_repulsion.setSingleStep(10)
self.spinBox_tf_link_net_repulsion.setProperty("value", 500)
self.spinBox_tf_link_net_repulsion.setObjectName("spinBox_tf_link_net_repulsion")
self.gridLayout_6.addWidget(self.spinBox_tf_link_net_repulsion, 2, 5, 1, 1)
+ self.label_16 = QtWidgets.QLabel(self.page_2)
+ self.label_16.setObjectName("label_16")
+ self.gridLayout_6.addWidget(self.label_16, 3, 4, 1, 1)
+ self.comboBox_tf_link_net_font_weight = QtWidgets.QComboBox(self.page_2)
+ self.comboBox_tf_link_net_font_weight.setObjectName("comboBox_tf_link_net_font_weight")
+ self.comboBox_tf_link_net_font_weight.addItem("")
+ self.comboBox_tf_link_net_font_weight.addItem("")
+ self.comboBox_tf_link_net_font_weight.addItem("")
+ self.comboBox_tf_link_net_font_weight.addItem("")
+ self.gridLayout_6.addWidget(self.comboBox_tf_link_net_font_weight, 3, 5, 1, 1)
self.gridLayout_4.addLayout(self.gridLayout_6, 2, 3, 1, 1)
self.gridLayout_8 = QtWidgets.QGridLayout()
self.gridLayout_8.setObjectName("gridLayout_8")
@@ -238,6 +248,11 @@ def retranslateUi(self, Settings):
self.label_14.setText(_translate("Settings", "Line Curve"))
self.lineEdit_tf_link_net_line_color.setText(_translate("Settings", "#9aa7b1"))
self.label_15.setText(_translate("Settings", "Repulsion"))
+ self.label_16.setText(_translate("Settings", "Font Weight"))
+ self.comboBox_tf_link_net_font_weight.setItemText(0, _translate("Settings", "bold"))
+ self.comboBox_tf_link_net_font_weight.setItemText(1, _translate("Settings", "normal"))
+ self.comboBox_tf_link_net_font_weight.setItemText(2, _translate("Settings", "bolder"))
+ self.comboBox_tf_link_net_font_weight.setItemText(3, _translate("Settings", "lighter"))
self.label_2.setText(_translate("Settings", "Linkage Method"))
self.comboBox_heatmap_linkage_method.setCurrentText(_translate("Settings", "average"))
self.comboBox_heatmap_linkage_method.setItemText(0, _translate("Settings", "average"))
diff --git a/utils/TaxaFuncPloter/network_plot.py b/utils/TaxaFuncPloter/network_plot.py
index de0f944..12506fa 100644
--- a/utils/TaxaFuncPloter/network_plot.py
+++ b/utils/TaxaFuncPloter/network_plot.py
@@ -16,13 +16,18 @@ def __init__(self, tfobj,
line_width=1.5,
line_curve=0.1,
line_color="#9aa7b1",
- repulsion=500
+ repulsion=500,
+ co_network_focus_color="#B24745",
+ co_network_normal_color="#79af97",
+ font_weight="normal"
):
self.tfa = tfobj
self.show_labels = show_labels
self.font_size = font_size
+ self.font_weight = font_weight
+
self.rename_taxa = rename_taxa
self.taxa_shape = taxa_shape
self.func_shape = func_shape
@@ -38,6 +43,9 @@ def __init__(self, tfobj,
self.repulsion = repulsion
+ self.co_network_focus_color = co_network_focus_color
+ self.co_network_normal_color = co_network_normal_color
+
def modify_focus_list(self, focus_list):
new_focus_list = []
@@ -144,8 +152,8 @@ def normalize(value):
return nodes, links, categories
else:
- nodes = [{"name": taxon, "category": 0, "symbolSize": normalize(taxa_sum[taxon]), "value": taxa_sum[taxon], "symbol": 'triangle'} for taxon in taxa] + \
- [{"name": function, "category": 1, "symbolSize": normalize(function_sum[function]), "value": function_sum[function], "symbol": 'circle'} for function in functions]
+ nodes = [{"name": taxon, "category": 0, "symbolSize": normalize(taxa_sum[taxon]), "value": taxa_sum[taxon], "symbol": self.taxa_shape} for taxon in taxa] + \
+ [{"name": function, "category": 1, "symbolSize": normalize(function_sum[function]), "value": function_sum[function], "symbol": self.func_shape} for function in functions]
links = [{"source": row["taxa"], "target": row["function"]} for _, row in df.iterrows()]
categories = [
@@ -220,11 +228,12 @@ def plot_tflink_network(self, sample_list:list = None, width:int = 12, height:in
color="auto",
formatter="{b}",
font_size=self.font_size,
+ font_weight=self.font_weight
),
)
.set_global_opts(
title_opts=opts.TitleOpts(
- title=f"Taxa-Functions Network",
+ title= "Taxa-Functions Network",
subtitle=f"{sample_list}" if sample_list else None,
subtitle_textstyle_opts=opts.TextStyleOpts(font_size=10),
),
@@ -263,7 +272,8 @@ def plot_tflink_network(self, sample_list:list = None, width:int = 12, height:in
def plot_co_expression_network(self, df_type:str= 'taxa', corr_method:str = 'pearson',
corr_threshold:float=0.5, sample_list:list = None,
- width:int = 12, height:int = 8, focus_list:list = [], plot_list_only:bool = False):
+ width:int = 12, height:int = 8, focus_list:list = [], plot_list_only:bool = False,
+ ):
from matplotlib import colormaps
#check sample_list length
if len(sample_list) < 2:
@@ -303,8 +313,8 @@ def plot_co_expression_network(self, df_type:str= 'taxa', corr_method:str = 'pea
max_node_size = node_sizes.max()
min_node_size = node_sizes.min()
- categories = [{"name": "Focused", "itemStyle": {"normal": {"color": "#ff0000"}}},
- {"name": "Normal", "itemStyle": {"normal": {"color": "#9AF10F"}}}]
+ categories = [{"name": "Focused", "itemStyle": {"normal": {"color": self.co_network_focus_color}}},
+ {"name": "Normal", "itemStyle": {"normal": {"color": self.co_network_normal_color}}}]
linked_nodes = set()
if focus_list:
@@ -326,16 +336,16 @@ def plot_co_expression_network(self, df_type:str= 'taxa', corr_method:str = 'pea
if item in focus_list: # mark the focus nodes with a different color
node_size = 50
- color = '#ff0000'
+ color = self.co_network_focus_color
category = 0 # Focus category
else:
node_size = (node_sizes[item] - min_node_size) / (max_node_size - min_node_size) * 30 + 10
- color = colormaps.get_cmap('viridis')(node_size / 40) # normalize the node size to [0, 1] for the color map
+ color = colormaps.get_cmap('viridis_r')(node_size / 40) # normalize the node size to [0, 1] for the color map
color = '#%02x%02x%02x' % (int(color[0]*255), int(color[1]*255), int(color[2]*255))
category = 1 # Normal category
else:
node_size = (node_sizes[item] - min_node_size) / (max_node_size - min_node_size) * 30 + 10
- color = colormaps.get_cmap('viridis')(node_size / 40) # normalize the node size to [0, 1] for the color map
+ color = colormaps.get_cmap('viridis_r')(node_size / 40) # normalize the node size to [0, 1] for the color map
color = '#%02x%02x%02x' % (int(color[0]*255), int(color[1]*255), int(color[2]*255))
category = 1 # Normal category
@@ -347,24 +357,24 @@ def plot_co_expression_network(self, df_type:str= 'taxa', corr_method:str = 'pea
})
links = []
+ # calculate the correlation between each pair of nodes, and create a link if the correlation is above a threshold
+ # the color of the link is determined by the correlation value
for i in range(len(correlation_matrix)):
for j in range(i+1, len(correlation_matrix)):
correlation = correlation_matrix.iloc[i, j]
# create a link if the correlation is above a threshold
if correlation > corr_threshold:
- color = colormaps.get_cmap('viridis')((correlation - corr_threshold) / corr_threshold)
+ color = colormaps.get_cmap('viridis')(1 - (correlation - corr_threshold) / corr_threshold)
color = '#%02x%02x%02x' % (int(color[0]*255), int(color[1]*255), int(color[2]*255))
- links.append({"source": correlation_matrix.columns[i], "target": correlation_matrix.columns[j], "value": correlation, "lineStyle": {"color": color}})
+ line_width = (correlation - corr_threshold) / (1 - corr_threshold) * self.line_width * 2
+ links.append({"source": correlation_matrix.columns[i], "target": correlation_matrix.columns[j], "value": correlation, "lineStyle": {"color": color, "width": line_width}})
pic = (
Graph(
init_opts=opts.InitOpts(
width=f"{width*100}px",
- height=f"{height*100}px",
- animation_opts=opts.AnimationOpts(
- animation_threshold=100, animation_easing="cubicOut"
- ),
+ height=f"{height*100}px"
)
)
.add(
@@ -379,7 +389,12 @@ def plot_co_expression_network(self, df_type:str= 'taxa', corr_method:str = 'pea
font_size=self.font_size,
position="right",
color="auto",
- formatter="{b}"
+ formatter="{b}",
+ font_weight=self.font_weight
+ ),
+ linestyle_opts=opts.LineStyleOpts(
+ opacity=self.line_opacity,
+ curve=self.line_curve
),
)
.set_global_opts(
diff --git a/utils/version.py b/utils/version.py
index 9c043c6..55702a1 100644
--- a/utils/version.py
+++ b/utils/version.py
@@ -1,2 +1,2 @@
-__version__ = '1.107.1'
+__version__ = '1.107.2'
API_version = '1'
\ No newline at end of file