From 003f32ce5e349bd4cf26b7fc052ae019c338781f Mon Sep 17 00:00:00 2001 From: Qing <44231502+byemaxx@users.noreply.github.com> Date: Fri, 9 Aug 2024 18:28:31 -0400 Subject: [PATCH] - Fix: Fixed the of test result table, the t-statistic was reversed. - New: adde z-score for heatmap scale. --- Docs/ChangeLog.md | 7 + metax/gui/main_gui.py | 39 +-- metax/gui/metax_gui/main_window.ui | 275 +++++++++------- metax/gui/metax_gui/ui_main_window.py | 160 ++++++---- .../analyzer_utils/cross_test.py | 4 + metax/taxafunc_ploter/basic_plot.py | 4 +- metax/taxafunc_ploter/heatmap_plot.py | 295 +++++++++++------- metax/utils/version.py | 2 +- 8 files changed, 465 insertions(+), 321 deletions(-) diff --git a/Docs/ChangeLog.md b/Docs/ChangeLog.md index 5e010f3..70a3cef 100644 --- a/Docs/ChangeLog.md +++ b/Docs/ChangeLog.md @@ -1,3 +1,10 @@ +# Version: 1.109.10 +## Date: 2024-08-9 +### Changes: +- Fix: Fixed the of test result table, the t-statistic was reversed. +- New: adde z-score for heatmap scale. + + # Version: 1.109.9 ## Date: 2024-08-7 ### Changes: diff --git a/metax/gui/main_gui.py b/metax/gui/main_gui.py index f418f61..cf40ceb 100644 --- a/metax/gui/main_gui.py +++ b/metax/gui/main_gui.py @@ -1175,7 +1175,7 @@ def save_set_multi_table_settings(self): def export_log_file(self): log_path = os.path.join(self.metax_home_path, "MetaX.log") - if os.path.exists(path): + if os.path.exists(log_path): #select a file to save # default output path is self.last_path file_path, _ = QFileDialog.getSaveFileName(self.MainWindow, "Export log file", self.last_path, "Log file (*.log)") @@ -2238,15 +2238,12 @@ def change_event_comboBox_top_heatmap_table(self): # selected_table_name = sender.currentText() selected_table_name = self.comboBox_top_heatmap_table.currentText() - scale_method_list = [self.comboBox_top_heatmap_scale.itemText(i) for i in range(self.comboBox_top_heatmap_scale.count())] if 'dunnett' in selected_table_name or 'deseq2' in selected_table_name: self.spinBox_top_heatmap_number.setEnabled(False) self.pushButton_plot_top_heatmap.setText('Plot Heatmap') self.pushButton_get_top_cross_table.setText('Get Heatmap Table') - # add 'all' to comboBox_top_heatmap_scale. - if 'all' not in scale_method_list: - self.comboBox_top_heatmap_scale.addItem('all') + if 'dunnett_test' in selected_table_name: self.comboBox_top_heatmap_sort_type.setEnabled(False) @@ -2295,9 +2292,7 @@ def change_event_comboBox_top_heatmap_table(self): self.pushButton_get_top_cross_table.setText('Get Top Table') self.comboBox_top_heatmap_sort_type.setEnabled(True) self.spinBox_top_heatmap_number.setEnabled(True) - # remove 'all' from comboBox_top_heatmap_scale. - if 'all' in scale_method_list: - self.comboBox_top_heatmap_scale.removeItem(scale_method_list.index('all')) + @@ -4292,6 +4287,7 @@ def plot_top_heatmap(self): pvalue = round(pvalue, 4) cmap = self.comboBox_top_heatmap_cmap.currentText() scale = self.comboBox_top_heatmap_scale.currentText() + scale_method = self.comboBox_top_heatmap_scale_method.currentText() rename_taxa = self.checkBox_top_heatmap_rename_taxa.isChecked() rename_sample = self.checkBox_top_heatmap_rename_sample.isChecked() show_all_labels = (self.checkBox_top_heatmap_show_all_labels_x.isChecked(), self.checkBox_top_heatmap_show_all_labels_y.isChecked()) @@ -4326,7 +4322,7 @@ def plot_top_heatmap(self): fig_size=fig_size, pvalue=pvalue, cmap=cmap, scale = scale, col_cluster = col_luster, row_cluster = row_luster, rename_taxa=rename_taxa, font_size=font_size, - show_all_labels = show_all_labels) + show_all_labels = show_all_labels, scale_method = scale_method) elif table_name.startswith('deseq2all'): p_type = self.comboBox_top_heatmap_sort_type.currentText() three_levels_df_type = self.comboBox_cross_3_level_plot_df_type.currentText() @@ -4338,7 +4334,8 @@ def plot_top_heatmap(self): scale = scale, col_cluster = col_luster, row_cluster = row_luster, rename_taxa=rename_taxa, font_size=font_size, show_all_labels = show_all_labels,return_type = 'fig', p_type = p_type, - three_levels_df_type = three_levels_df_type,remove_zero_col = remove_zero_col + three_levels_df_type = three_levels_df_type,remove_zero_col = remove_zero_col, + scale_method = scale_method ) # if fig is a tuple @@ -4356,7 +4353,8 @@ def plot_top_heatmap(self): scale = scale, col_cluster = col_luster, row_cluster = row_luster, rename_taxa=rename_taxa, font_size=font_size, show_all_labels = show_all_labels,return_type = 'fig', - three_levels_df_type = three_levels_df_type,remove_zero_col = remove_zero_col + three_levels_df_type = three_levels_df_type,remove_zero_col = remove_zero_col, + scale_method = scale_method ) # if fig is a tuple @@ -4388,13 +4386,14 @@ def plot_top_heatmap(self): top_number=top_num, value_type=value_type, fig_size=fig_size, col_cluster = col_luster, row_cluster = row_luster, pvalue=pvalue, cmap=cmap, rename_taxa=rename_taxa, font_size=font_size, title=title, - show_all_labels = show_all_labels) + show_all_labels = show_all_labels, scale = scale, scale_method = scale_method) else: fig = HeatmapPlot(self.tfa, **self.heatmap_params_dict).plot_basic_heatmap_of_test_res(df=df, top_number=top_num, value_type=value_type, fig_size=fig_size, pvalue=pvalue, scale = scale, col_cluster = col_luster, row_cluster = row_luster, cmap = cmap, rename_taxa=rename_taxa, font_size=font_size, - show_all_labels = show_all_labels, rename_sample = rename_sample) + show_all_labels = show_all_labels, rename_sample = rename_sample, + sort_by = sort_by, scale_method = scale_method) except Exception as e: error_message = traceback.format_exc() @@ -4413,6 +4412,7 @@ def get_top_cross_table(self): pvalue = self.doubleSpinBox_top_heatmap_pvalue.value() pvalue = round(pvalue, 4) scale = self.comboBox_top_heatmap_scale.currentText() + scale_method = self.comboBox_top_heatmap_scale_method.currentText() rename_taxa = self.checkBox_top_heatmap_rename_taxa.isChecked() col_luster = self.checkBox_cross_heatmap_col_cluster.isChecked() row_luster = self.checkBox_cross_heatmap_row_cluster.isChecked() @@ -4429,7 +4429,7 @@ def get_top_cross_table(self): if table_name.startswith('dunnett_test'): df_top_cross = HeatmapPlot(self.tfa, **self.heatmap_params_dict).get_heatmap_table_of_dunnett_res(df = df, pvalue=pvalue,scale = scale, col_cluster = col_luster, row_cluster = row_luster, - rename_taxa=rename_taxa) + rename_taxa=rename_taxa, scale_method = scale_method) elif 'deseq2all' in table_name: p_type = self.comboBox_top_heatmap_sort_type.currentText() df_top_cross = HeatmapPlot(self.tfa, **self.heatmap_params_dict).plot_heatmap_of_all_condition_res(df = df, res_df_type='deseq2', @@ -4439,7 +4439,7 @@ def get_top_cross_table(self): col_cluster = col_luster, row_cluster = row_luster, rename_taxa=rename_taxa, return_type = 'table', p_type = p_type, three_levels_df_type = self.comboBox_cross_3_level_plot_df_type.currentText(), - remove_zero_col = remove_zero_col + remove_zero_col = remove_zero_col, scale_method = scale_method ) elif 'dunnettAllCondtion' in table_name: df_top_cross = HeatmapPlot(self.tfa, **self.heatmap_params_dict).plot_heatmap_of_all_condition_res(df = df, res_df_type='dunnett', @@ -4447,7 +4447,7 @@ def get_top_cross_table(self): col_cluster = col_luster, row_cluster = row_luster, rename_taxa=rename_taxa, return_type = 'table', three_levels_df_type = self.comboBox_cross_3_level_plot_df_type.currentText(), - remove_zero_col = remove_zero_col + remove_zero_col = remove_zero_col, scale_method = scale_method ) @@ -4456,12 +4456,13 @@ def get_top_cross_table(self): df_top_cross = HeatmapPlot(self.tfa, **self.heatmap_params_dict).get_top_across_table(df=df, top_number=top_num, col_cluster = col_luster, row_cluster = row_luster, value_type=value_type, pvalue=pvalue, - rename_taxa=rename_taxa) - else: + rename_taxa=rename_taxa, scale = scale, scale_method = scale_method) + else: # get result of test and anova of [taxa, functions, peptides and custom table] + # get the intensity of the result items which are significant df_top_cross = HeatmapPlot(self.tfa, **self.heatmap_params_dict).get_top_across_table_basic(df=df, top_number=top_num, col_cluster = col_luster, row_cluster = row_luster, value_type=value_type, pvalue=pvalue, - scale = scale, rename_taxa=rename_taxa) + scale = scale, rename_taxa=rename_taxa, scale_method = scale_method) except ValueError as e: QMessageBox.warning(self.MainWindow, 'Warning', f'No significant results.\n\n{e}') return None diff --git a/metax/gui/metax_gui/main_window.ui b/metax/gui/metax_gui/main_window.ui index 011bfd9..2844d1d 100644 --- a/metax/gui/metax_gui/main_window.ui +++ b/metax/gui/metax_gui/main_window.ui @@ -7,7 +7,7 @@ 0 0 1122 - 707 + 794 @@ -246,7 +246,7 @@ 0 0 528 - 486 + 573 @@ -1371,7 +1371,7 @@ 16777215 - 250 + 280 @@ -1400,7 +1400,7 @@ 0 0 - 660 + 1016 232 @@ -2376,7 +2376,7 @@ - + 0 0 @@ -2654,7 +2654,7 @@ 16777215 - 250 + 280 @@ -2671,8 +2671,8 @@ 0 0 - 999 - 150 + 1016 + 162 @@ -2811,6 +2811,11 @@ column + + + all + + None @@ -3640,7 +3645,7 @@ 16777215 - 220 + 240 @@ -3670,7 +3675,7 @@ 0 0 1003 - 124 + 126 @@ -3800,6 +3805,11 @@ column + + + all + + None @@ -3809,57 +3819,6 @@ - - - - - - - 0 - 0 - - - - - 0 - 0 - - - - - 16777215 - 16777215 - - - - Theme - - - - - - - - 0 - 0 - - - - - 0 - 0 - - - - - 16777215 - 16777215 - - - - - - @@ -4099,7 +4058,7 @@ - + 0 0 @@ -4159,6 +4118,92 @@ + + + + + + + 0 + 0 + + + + + 0 + 0 + + + + + 16777215 + 16777215 + + + + Colors + + + + + + + + 0 + 0 + + + + + 0 + 0 + + + + + 16777215 + 16777215 + + + + + + + + + + + + + 0 + 0 + + + + + 0 + 0 + + + + + 16777215 + 16777215 + + + + + 75 + true + + + + T & ANOVA + + + + + @@ -4221,48 +4266,6 @@ - - - - - - - 0 - 0 - - - - - 0 - 0 - - - - - 16777215 - 16777215 - - - - - 75 - true - - - - T & ANOVA - - - - - - - - - p - - - @@ -4612,6 +4615,43 @@ + + + + + + + 0 + 0 + + + + with + + + + + + + + 0 + 0 + + + + + maxmin + + + + + zscore + + + + + + @@ -5501,9 +5541,9 @@ 0 - -17 - 979 - 94 + 0 + 996 + 146 @@ -6021,7 +6061,7 @@ QTabWidget::Triangular - 1 + 0 @@ -6053,8 +6093,8 @@ 0 0 - 493 - 128 + 1016 + 181 @@ -7284,7 +7324,7 @@ 0 0 1016 - 69 + 144 @@ -7615,7 +7655,7 @@ QTabWidget::Triangular - 1 + 0 @@ -8131,8 +8171,8 @@ 0 0 - 775 - 102 + 1016 + 185 @@ -8518,6 +8558,11 @@ column + + + all + + None @@ -9047,7 +9092,7 @@ 0 0 1016 - 93 + 168 diff --git a/metax/gui/metax_gui/ui_main_window.py b/metax/gui/metax_gui/ui_main_window.py index 804aa5f..bf9e99b 100644 --- a/metax/gui/metax_gui/ui_main_window.py +++ b/metax/gui/metax_gui/ui_main_window.py @@ -14,7 +14,7 @@ class Ui_metaX_main(object): def setupUi(self, metaX_main): metaX_main.setObjectName("metaX_main") - metaX_main.resize(1122, 707) + metaX_main.resize(1122, 794) sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) @@ -147,7 +147,7 @@ def setupUi(self, metaX_main): self.toolBox_2.setMaximumSize(QtCore.QSize(1677, 16777215)) self.toolBox_2.setObjectName("toolBox_2") self.page_2 = QtWidgets.QWidget() - self.page_2.setGeometry(QtCore.QRect(0, 0, 528, 486)) + self.page_2.setGeometry(QtCore.QRect(0, 0, 528, 573)) self.page_2.setObjectName("page_2") self.gridLayout_27 = QtWidgets.QGridLayout(self.page_2) self.gridLayout_27.setObjectName("gridLayout_27") @@ -692,7 +692,7 @@ def setupUi(self, metaX_main): self.line_7.setObjectName("line_7") self.gridLayout_26.addWidget(self.line_7, 1, 0, 1, 3) self.groupBox_basic_plot = QtWidgets.QGroupBox(self.tab_12) - self.groupBox_basic_plot.setMaximumSize(QtCore.QSize(16777215, 250)) + self.groupBox_basic_plot.setMaximumSize(QtCore.QSize(16777215, 280)) self.groupBox_basic_plot.setObjectName("groupBox_basic_plot") self.gridLayout_40 = QtWidgets.QGridLayout(self.groupBox_basic_plot) self.gridLayout_40.setObjectName("gridLayout_40") @@ -706,7 +706,7 @@ def setupUi(self, metaX_main): self.scrollArea.setWidgetResizable(True) self.scrollArea.setObjectName("scrollArea") self.scrollAreaWidgetContents = QtWidgets.QWidget() - self.scrollAreaWidgetContents.setGeometry(QtCore.QRect(0, 0, 660, 232)) + self.scrollAreaWidgetContents.setGeometry(QtCore.QRect(0, 0, 1016, 232)) self.scrollAreaWidgetContents.setObjectName("scrollAreaWidgetContents") self.gridLayout_34 = QtWidgets.QGridLayout(self.scrollAreaWidgetContents) self.gridLayout_34.setObjectName("gridLayout_34") @@ -1209,7 +1209,7 @@ def setupUi(self, metaX_main): self.label_70.setObjectName("label_70") self.horizontalLayout_35.addWidget(self.label_70) self.comboBox_table4pca = QtWidgets.QComboBox(self.tab_12) - sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Preferred) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Maximum) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth(self.comboBox_table4pca.sizePolicy().hasHeightForWidth()) @@ -1362,7 +1362,7 @@ def setupUi(self, metaX_main): self.pushButton_basic_heatmap_add.setObjectName("pushButton_basic_heatmap_add") self.gridLayout_23.addWidget(self.pushButton_basic_heatmap_add, 5, 3, 1, 1) self.groupBox_basic_heatmap_plot_settings = QtWidgets.QGroupBox(self.tab_13) - self.groupBox_basic_heatmap_plot_settings.setMaximumSize(QtCore.QSize(16777215, 250)) + self.groupBox_basic_heatmap_plot_settings.setMaximumSize(QtCore.QSize(16777215, 280)) self.groupBox_basic_heatmap_plot_settings.setObjectName("groupBox_basic_heatmap_plot_settings") self.gridLayout_41 = QtWidgets.QGridLayout(self.groupBox_basic_heatmap_plot_settings) self.gridLayout_41.setObjectName("gridLayout_41") @@ -1370,7 +1370,7 @@ def setupUi(self, metaX_main): self.scrollArea_2.setWidgetResizable(True) self.scrollArea_2.setObjectName("scrollArea_2") self.scrollAreaWidgetContents_2 = QtWidgets.QWidget() - self.scrollAreaWidgetContents_2.setGeometry(QtCore.QRect(0, 0, 999, 150)) + self.scrollAreaWidgetContents_2.setGeometry(QtCore.QRect(0, 0, 1016, 162)) self.scrollAreaWidgetContents_2.setObjectName("scrollAreaWidgetContents_2") self.gridLayout_50 = QtWidgets.QGridLayout(self.scrollAreaWidgetContents_2) self.gridLayout_50.setObjectName("gridLayout_50") @@ -1453,6 +1453,7 @@ def setupUi(self, metaX_main): self.comboBox_basic_hetatmap_scale.addItem("") self.comboBox_basic_hetatmap_scale.addItem("") self.comboBox_basic_hetatmap_scale.addItem("") + self.comboBox_basic_hetatmap_scale.addItem("") self.horizontalLayout_87.addWidget(self.comboBox_basic_hetatmap_scale) self.label_13 = QtWidgets.QLabel(self.scrollAreaWidgetContents_2) sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Preferred) @@ -1904,7 +1905,7 @@ def setupUi(self, metaX_main): self.gridLayout_46.addWidget(self.checkBox_2, 1, 0, 1, 1) self.gridLayout_75.addLayout(self.gridLayout_46, 0, 0, 1, 1) self.groupBox_cross_heatmap_settings = QtWidgets.QGroupBox(self.groupBox_cross_heatmap_plot) - self.groupBox_cross_heatmap_settings.setMaximumSize(QtCore.QSize(16777215, 220)) + self.groupBox_cross_heatmap_settings.setMaximumSize(QtCore.QSize(16777215, 240)) self.groupBox_cross_heatmap_settings.setObjectName("groupBox_cross_heatmap_settings") self.gridLayout_52 = QtWidgets.QGridLayout(self.groupBox_cross_heatmap_settings) self.gridLayout_52.setObjectName("gridLayout_52") @@ -1918,7 +1919,7 @@ def setupUi(self, metaX_main): self.scrollArea_cross_heatmap_settings.setWidgetResizable(True) self.scrollArea_cross_heatmap_settings.setObjectName("scrollArea_cross_heatmap_settings") self.scrollAreaWidgetContents_3 = QtWidgets.QWidget() - self.scrollAreaWidgetContents_3.setGeometry(QtCore.QRect(0, 0, 1003, 124)) + self.scrollAreaWidgetContents_3.setGeometry(QtCore.QRect(0, 0, 1003, 126)) self.scrollAreaWidgetContents_3.setObjectName("scrollAreaWidgetContents_3") self.gridLayout_38 = QtWidgets.QGridLayout(self.scrollAreaWidgetContents_3) self.gridLayout_38.setObjectName("gridLayout_38") @@ -1981,31 +1982,9 @@ def setupUi(self, metaX_main): self.comboBox_top_heatmap_scale.addItem("") self.comboBox_top_heatmap_scale.addItem("") self.comboBox_top_heatmap_scale.addItem("") + self.comboBox_top_heatmap_scale.addItem("") self.horizontalLayout_19.addWidget(self.comboBox_top_heatmap_scale) self.gridLayout_51.addLayout(self.horizontalLayout_19, 1, 1, 1, 1) - self.horizontalLayout_21 = QtWidgets.QHBoxLayout() - self.horizontalLayout_21.setObjectName("horizontalLayout_21") - self.label_38 = QtWidgets.QLabel(self.scrollAreaWidgetContents_3) - sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Preferred) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.label_38.sizePolicy().hasHeightForWidth()) - self.label_38.setSizePolicy(sizePolicy) - self.label_38.setMinimumSize(QtCore.QSize(0, 0)) - self.label_38.setMaximumSize(QtCore.QSize(16777215, 16777215)) - self.label_38.setObjectName("label_38") - self.horizontalLayout_21.addWidget(self.label_38) - self.comboBox_top_heatmap_cmap = QtWidgets.QComboBox(self.scrollAreaWidgetContents_3) - sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Fixed) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.comboBox_top_heatmap_cmap.sizePolicy().hasHeightForWidth()) - self.comboBox_top_heatmap_cmap.setSizePolicy(sizePolicy) - self.comboBox_top_heatmap_cmap.setMinimumSize(QtCore.QSize(0, 0)) - self.comboBox_top_heatmap_cmap.setMaximumSize(QtCore.QSize(16777215, 16777215)) - self.comboBox_top_heatmap_cmap.setObjectName("comboBox_top_heatmap_cmap") - self.horizontalLayout_21.addWidget(self.comboBox_top_heatmap_cmap) - self.gridLayout_51.addLayout(self.horizontalLayout_21, 1, 2, 1, 1) self.label_153 = QtWidgets.QLabel(self.scrollAreaWidgetContents_3) self.label_153.setMinimumSize(QtCore.QSize(0, 0)) self.label_153.setMaximumSize(QtCore.QSize(16777215, 16777215)) @@ -2111,7 +2090,7 @@ def setupUi(self, metaX_main): self.horizontalLayout_16 = QtWidgets.QHBoxLayout() self.horizontalLayout_16.setObjectName("horizontalLayout_16") self.label_59 = QtWidgets.QLabel(self.scrollAreaWidgetContents_3) - sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Preferred) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth(self.label_59.sizePolicy().hasHeightForWidth()) @@ -2137,29 +2116,29 @@ def setupUi(self, metaX_main): self.gridLayout_51.addLayout(self.horizontalLayout_16, 0, 1, 1, 1) self.horizontalLayout_86 = QtWidgets.QHBoxLayout() self.horizontalLayout_86.setObjectName("horizontalLayout_86") - self.label_57 = QtWidgets.QLabel(self.scrollAreaWidgetContents_3) - sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Preferred) + self.horizontalLayout_21 = QtWidgets.QHBoxLayout() + self.horizontalLayout_21.setObjectName("horizontalLayout_21") + self.label_38 = QtWidgets.QLabel(self.scrollAreaWidgetContents_3) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Preferred) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.label_57.sizePolicy().hasHeightForWidth()) - self.label_57.setSizePolicy(sizePolicy) - self.label_57.setMinimumSize(QtCore.QSize(0, 0)) - self.label_57.setMaximumSize(QtCore.QSize(16777215, 16777215)) - self.label_57.setObjectName("label_57") - self.horizontalLayout_86.addWidget(self.label_57) - self.comboBox_top_heatmap_sort_type = QtWidgets.QComboBox(self.scrollAreaWidgetContents_3) + sizePolicy.setHeightForWidth(self.label_38.sizePolicy().hasHeightForWidth()) + self.label_38.setSizePolicy(sizePolicy) + self.label_38.setMinimumSize(QtCore.QSize(0, 0)) + self.label_38.setMaximumSize(QtCore.QSize(16777215, 16777215)) + self.label_38.setObjectName("label_38") + self.horizontalLayout_21.addWidget(self.label_38) + self.comboBox_top_heatmap_cmap = QtWidgets.QComboBox(self.scrollAreaWidgetContents_3) sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Fixed) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.comboBox_top_heatmap_sort_type.sizePolicy().hasHeightForWidth()) - self.comboBox_top_heatmap_sort_type.setSizePolicy(sizePolicy) - self.comboBox_top_heatmap_sort_type.setMinimumSize(QtCore.QSize(0, 0)) - self.comboBox_top_heatmap_sort_type.setMaximumSize(QtCore.QSize(16777215, 16777215)) - self.comboBox_top_heatmap_sort_type.setObjectName("comboBox_top_heatmap_sort_type") - self.comboBox_top_heatmap_sort_type.addItem("") - self.comboBox_top_heatmap_sort_type.addItem("") - self.comboBox_top_heatmap_sort_type.addItem("") - self.horizontalLayout_86.addWidget(self.comboBox_top_heatmap_sort_type) + sizePolicy.setHeightForWidth(self.comboBox_top_heatmap_cmap.sizePolicy().hasHeightForWidth()) + self.comboBox_top_heatmap_cmap.setSizePolicy(sizePolicy) + self.comboBox_top_heatmap_cmap.setMinimumSize(QtCore.QSize(0, 0)) + self.comboBox_top_heatmap_cmap.setMaximumSize(QtCore.QSize(16777215, 16777215)) + self.comboBox_top_heatmap_cmap.setObjectName("comboBox_top_heatmap_cmap") + self.horizontalLayout_21.addWidget(self.comboBox_top_heatmap_cmap) + self.horizontalLayout_86.addLayout(self.horizontalLayout_21) self.gridLayout_51.addLayout(self.horizontalLayout_86, 1, 3, 1, 1) self.label_180 = QtWidgets.QLabel(self.scrollAreaWidgetContents_3) sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Preferred) @@ -2177,9 +2156,29 @@ def setupUi(self, metaX_main): self.gridLayout_51.addWidget(self.label_180, 2, 0, 1, 1) self.horizontalLayout_93 = QtWidgets.QHBoxLayout() self.horizontalLayout_93.setObjectName("horizontalLayout_93") - self.label_30 = QtWidgets.QLabel(self.scrollAreaWidgetContents_3) - self.label_30.setObjectName("label_30") - self.horizontalLayout_93.addWidget(self.label_30) + self.label_57 = QtWidgets.QLabel(self.scrollAreaWidgetContents_3) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Preferred) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.label_57.sizePolicy().hasHeightForWidth()) + self.label_57.setSizePolicy(sizePolicy) + self.label_57.setMinimumSize(QtCore.QSize(0, 0)) + self.label_57.setMaximumSize(QtCore.QSize(16777215, 16777215)) + self.label_57.setObjectName("label_57") + self.horizontalLayout_93.addWidget(self.label_57) + self.comboBox_top_heatmap_sort_type = QtWidgets.QComboBox(self.scrollAreaWidgetContents_3) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Fixed) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.comboBox_top_heatmap_sort_type.sizePolicy().hasHeightForWidth()) + self.comboBox_top_heatmap_sort_type.setSizePolicy(sizePolicy) + self.comboBox_top_heatmap_sort_type.setMinimumSize(QtCore.QSize(0, 0)) + self.comboBox_top_heatmap_sort_type.setMaximumSize(QtCore.QSize(16777215, 16777215)) + self.comboBox_top_heatmap_sort_type.setObjectName("comboBox_top_heatmap_sort_type") + self.comboBox_top_heatmap_sort_type.addItem("") + self.comboBox_top_heatmap_sort_type.addItem("") + self.comboBox_top_heatmap_sort_type.addItem("") + self.horizontalLayout_93.addWidget(self.comboBox_top_heatmap_sort_type) self.doubleSpinBox_top_heatmap_pvalue = QtWidgets.QDoubleSpinBox(self.scrollAreaWidgetContents_3) sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Fixed) sizePolicy.setHorizontalStretch(0) @@ -2314,6 +2313,27 @@ def setupUi(self, metaX_main): self.checkBox_cross_3_level_plot_remove_zero_col.setChecked(True) self.checkBox_cross_3_level_plot_remove_zero_col.setObjectName("checkBox_cross_3_level_plot_remove_zero_col") self.gridLayout_51.addWidget(self.checkBox_cross_3_level_plot_remove_zero_col, 3, 5, 1, 1) + self.horizontalLayout_48 = QtWidgets.QHBoxLayout() + self.horizontalLayout_48.setObjectName("horizontalLayout_48") + self.label_30 = QtWidgets.QLabel(self.scrollAreaWidgetContents_3) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Preferred) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.label_30.sizePolicy().hasHeightForWidth()) + self.label_30.setSizePolicy(sizePolicy) + self.label_30.setObjectName("label_30") + self.horizontalLayout_48.addWidget(self.label_30) + self.comboBox_top_heatmap_scale_method = QtWidgets.QComboBox(self.scrollAreaWidgetContents_3) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Fixed) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.comboBox_top_heatmap_scale_method.sizePolicy().hasHeightForWidth()) + self.comboBox_top_heatmap_scale_method.setSizePolicy(sizePolicy) + self.comboBox_top_heatmap_scale_method.setObjectName("comboBox_top_heatmap_scale_method") + self.comboBox_top_heatmap_scale_method.addItem("") + self.comboBox_top_heatmap_scale_method.addItem("") + self.horizontalLayout_48.addWidget(self.comboBox_top_heatmap_scale_method) + self.gridLayout_51.addLayout(self.horizontalLayout_48, 1, 2, 1, 1) self.gridLayout_38.addLayout(self.gridLayout_51, 0, 1, 1, 1) self.scrollArea_cross_heatmap_settings.setWidget(self.scrollAreaWidgetContents_3) self.gridLayout_52.addWidget(self.scrollArea_cross_heatmap_settings, 0, 0, 1, 1) @@ -2824,7 +2844,7 @@ def setupUi(self, metaX_main): self.scrollArea_3.setWidgetResizable(True) self.scrollArea_3.setObjectName("scrollArea_3") self.scrollAreaWidgetContents_4 = QtWidgets.QWidget() - self.scrollAreaWidgetContents_4.setGeometry(QtCore.QRect(0, -17, 979, 94)) + self.scrollAreaWidgetContents_4.setGeometry(QtCore.QRect(0, 0, 996, 146)) self.scrollAreaWidgetContents_4.setObjectName("scrollAreaWidgetContents_4") self.gridLayout_68 = QtWidgets.QGridLayout(self.scrollAreaWidgetContents_4) self.gridLayout_68.setObjectName("gridLayout_68") @@ -3125,7 +3145,7 @@ def setupUi(self, metaX_main): self.scrollArea_4.setWidgetResizable(True) self.scrollArea_4.setObjectName("scrollArea_4") self.scrollAreaWidgetContents_5 = QtWidgets.QWidget() - self.scrollAreaWidgetContents_5.setGeometry(QtCore.QRect(0, 0, 493, 128)) + self.scrollAreaWidgetContents_5.setGeometry(QtCore.QRect(0, 0, 1016, 181)) self.scrollAreaWidgetContents_5.setObjectName("scrollAreaWidgetContents_5") self.gridLayout_49 = QtWidgets.QGridLayout(self.scrollAreaWidgetContents_5) self.gridLayout_49.setObjectName("gridLayout_49") @@ -3770,7 +3790,7 @@ def setupUi(self, metaX_main): self.scrollArea_5.setWidgetResizable(True) self.scrollArea_5.setObjectName("scrollArea_5") self.scrollAreaWidgetContents_6 = QtWidgets.QWidget() - self.scrollAreaWidgetContents_6.setGeometry(QtCore.QRect(0, 0, 1016, 69)) + self.scrollAreaWidgetContents_6.setGeometry(QtCore.QRect(0, 0, 1016, 144)) self.scrollAreaWidgetContents_6.setObjectName("scrollAreaWidgetContents_6") self.gridLayout_57 = QtWidgets.QGridLayout(self.scrollAreaWidgetContents_6) self.gridLayout_57.setObjectName("gridLayout_57") @@ -4241,7 +4261,7 @@ def setupUi(self, metaX_main): self.scrollArea_6.setWidgetResizable(True) self.scrollArea_6.setObjectName("scrollArea_6") self.scrollAreaWidgetContents_7 = QtWidgets.QWidget() - self.scrollAreaWidgetContents_7.setGeometry(QtCore.QRect(0, 0, 775, 102)) + self.scrollAreaWidgetContents_7.setGeometry(QtCore.QRect(0, 0, 1016, 185)) self.scrollAreaWidgetContents_7.setObjectName("scrollAreaWidgetContents_7") self.gridLayout_69 = QtWidgets.QGridLayout(self.scrollAreaWidgetContents_7) self.gridLayout_69.setObjectName("gridLayout_69") @@ -4470,6 +4490,7 @@ def setupUi(self, metaX_main): self.comboBox_tflink_hetatmap_scale.addItem("") self.comboBox_tflink_hetatmap_scale.addItem("") self.comboBox_tflink_hetatmap_scale.addItem("") + self.comboBox_tflink_hetatmap_scale.addItem("") self.horizontalLayout_47.addWidget(self.comboBox_tflink_hetatmap_scale) self.label_61 = QtWidgets.QLabel(self.scrollAreaWidgetContents_7) sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Preferred) @@ -4744,7 +4765,7 @@ def setupUi(self, metaX_main): self.scrollArea_7.setWidgetResizable(True) self.scrollArea_7.setObjectName("scrollArea_7") self.scrollAreaWidgetContents_8 = QtWidgets.QWidget() - self.scrollAreaWidgetContents_8.setGeometry(QtCore.QRect(0, 0, 1016, 93)) + self.scrollAreaWidgetContents_8.setGeometry(QtCore.QRect(0, 0, 1016, 168)) self.scrollAreaWidgetContents_8.setObjectName("scrollAreaWidgetContents_8") self.gridLayout_66 = QtWidgets.QGridLayout(self.scrollAreaWidgetContents_8) self.gridLayout_66.setObjectName("gridLayout_66") @@ -5319,8 +5340,8 @@ def setupUi(self, metaX_main): self.toolBox_2.setCurrentIndex(0) self.tabWidget_4.setCurrentIndex(1) self.tabWidget_3.setCurrentIndex(3) - self.tabWidget.setCurrentIndex(1) - self.tabWidget_2.setCurrentIndex(1) + self.tabWidget.setCurrentIndex(0) + self.tabWidget_2.setCurrentIndex(0) self.tabWidget_6.setCurrentIndex(1) self.toolBox_metalab_res_anno.setCurrentIndex(0) self.tabWidget_5.setCurrentIndex(0) @@ -5596,7 +5617,8 @@ def retranslateUi(self, metaX_main): self.label_31.setText(_translate("metaX_main", "Scale")) self.comboBox_basic_hetatmap_scale.setItemText(0, _translate("metaX_main", "row")) self.comboBox_basic_hetatmap_scale.setItemText(1, _translate("metaX_main", "column")) - self.comboBox_basic_hetatmap_scale.setItemText(2, _translate("metaX_main", "None")) + self.comboBox_basic_hetatmap_scale.setItemText(2, _translate("metaX_main", "all")) + self.comboBox_basic_hetatmap_scale.setItemText(3, _translate("metaX_main", "None")) self.label_13.setText(_translate("metaX_main", "Theme")) self.checkBox_basic_hetatmap_row_cluster.setText(_translate("metaX_main", "Row Cluster")) self.label_183.setText(_translate("metaX_main", "General")) @@ -5660,8 +5682,8 @@ def retranslateUi(self, metaX_main): self.label_62.setText(_translate("metaX_main", "Scale By")) self.comboBox_top_heatmap_scale.setItemText(0, _translate("metaX_main", "row")) self.comboBox_top_heatmap_scale.setItemText(1, _translate("metaX_main", "column")) - self.comboBox_top_heatmap_scale.setItemText(2, _translate("metaX_main", "None")) - self.label_38.setText(_translate("metaX_main", "Theme")) + self.comboBox_top_heatmap_scale.setItemText(2, _translate("metaX_main", "all")) + self.comboBox_top_heatmap_scale.setItemText(3, _translate("metaX_main", "None")) self.label_153.setText(_translate("metaX_main", "Rename")) self.label_109.setText(_translate("metaX_main", "Font Size")) self.label_60.setText(_translate("metaX_main", "Height")) @@ -5670,12 +5692,12 @@ def retranslateUi(self, metaX_main): self.label_181.setText(_translate("metaX_main", "Group-Control")) self.label_182.setText(_translate("metaX_main", "General")) self.label_59.setText(_translate("metaX_main", "Width")) + self.label_38.setText(_translate("metaX_main", "Colors")) + self.label_180.setText(_translate("metaX_main", "T & ANOVA")) self.label_57.setText(_translate("metaX_main", "Sort By")) self.comboBox_top_heatmap_sort_type.setItemText(0, _translate("metaX_main", "p-value")) self.comboBox_top_heatmap_sort_type.setItemText(1, _translate("metaX_main", "f-statistic (ANOVA)")) self.comboBox_top_heatmap_sort_type.setItemText(2, _translate("metaX_main", "t-statistic (T-Test)")) - self.label_180.setText(_translate("metaX_main", "T & ANOVA")) - self.label_30.setText(_translate("metaX_main", "p")) self.checkBox_cross_heatmap_row_cluster.setText(_translate("metaX_main", "Row Cluster")) self.checkBox_cross_heatmap_col_cluster.setText(_translate("metaX_main", "Col Cluster")) self.label_138.setText(_translate("metaX_main", "Log2FC")) @@ -5686,6 +5708,9 @@ def retranslateUi(self, metaX_main): self.comboBox_cross_3_level_plot_df_type.setItemText(1, _translate("metaX_main", "no_na")) self.comboBox_cross_3_level_plot_df_type.setItemText(2, _translate("metaX_main", "same_trends")) self.checkBox_cross_3_level_plot_remove_zero_col.setText(_translate("metaX_main", "Remove Zero Col")) + self.label_30.setText(_translate("metaX_main", "with")) + self.comboBox_top_heatmap_scale_method.setItemText(0, _translate("metaX_main", "maxmin")) + self.comboBox_top_heatmap_scale_method.setItemText(1, _translate("metaX_main", "zscore")) self.label_36.setText(_translate("metaX_main", "Table")) self.comboBox_table_for_ttest.setItemText(0, _translate("metaX_main", "Taxa-Functions")) self.comboBox_table_for_ttest.setItemText(1, _translate("metaX_main", "Taxa")) @@ -5929,7 +5954,8 @@ def retranslateUi(self, metaX_main): self.label_23.setText(_translate("metaX_main", "Scale")) self.comboBox_tflink_hetatmap_scale.setItemText(0, _translate("metaX_main", "row")) self.comboBox_tflink_hetatmap_scale.setItemText(1, _translate("metaX_main", "column")) - self.comboBox_tflink_hetatmap_scale.setItemText(2, _translate("metaX_main", "None")) + self.comboBox_tflink_hetatmap_scale.setItemText(2, _translate("metaX_main", "all")) + self.comboBox_tflink_hetatmap_scale.setItemText(3, _translate("metaX_main", "None")) self.label_61.setText(_translate("metaX_main", "Theme")) self.tabWidget_2.setTabText(self.tabWidget_2.indexOf(self.tab_8), _translate("metaX_main", "Taxa-Func Link")) self.radioButton_network_bysample.setText(_translate("metaX_main", "Sample")) diff --git a/metax/taxafunc_analyzer/analyzer_utils/cross_test.py b/metax/taxafunc_analyzer/analyzer_utils/cross_test.py index fcc452f..bd25fe6 100644 --- a/metax/taxafunc_analyzer/analyzer_utils/cross_test.py +++ b/metax/taxafunc_analyzer/analyzer_utils/cross_test.py @@ -151,6 +151,10 @@ def get_stats_ttest(self, group_list: list = None, df_type: str = 'taxa-func', c res["t-statistic"].append(t) res = pd.DataFrame(res) + + # print('reverse the t-statistic value due to the order of group_list is not correct') + res['t-statistic'] = -res['t-statistic'] + on_values = [primary] if df_type in ['taxa-func', 'func-taxa']: on_values.append(secondary) diff --git a/metax/taxafunc_ploter/basic_plot.py b/metax/taxafunc_ploter/basic_plot.py index 4f597d4..05d4c9d 100644 --- a/metax/taxafunc_ploter/basic_plot.py +++ b/metax/taxafunc_ploter/basic_plot.py @@ -402,7 +402,7 @@ def plot_corr_sns( cbar = fig.ax_heatmap.collections[0].colorbar cbar.set_label('Intensity', rotation=90, labelpad=1) cbar.ax.yaxis.set_ticks_position('left') - cbar.ax.yaxis.set_label_position('left') + cbar.ax.yaxis.set_label_position('right') plt.subplots_adjust(left=0.03, bottom=0.095, right=0.5, top=0.96, wspace=0.01, hspace=0.01) plt.tight_layout() @@ -624,7 +624,7 @@ def plot_items_corr_heatmap( cbar = fig.ax_heatmap.collections[0].colorbar cbar.set_label("Correlation", rotation=90, labelpad=1) cbar.ax.yaxis.set_ticks_position('left') - cbar.ax.yaxis.set_label_position('left') + cbar.ax.yaxis.set_label_position('right') plt.subplots_adjust(left=0.03, bottom=0.095, right=0.5, top=0.96, wspace=0.01, hspace=0.01) plt.tight_layout() diff --git a/metax/taxafunc_ploter/heatmap_plot.py b/metax/taxafunc_ploter/heatmap_plot.py index 303d3b1..fe4043c 100644 --- a/metax/taxafunc_ploter/heatmap_plot.py +++ b/metax/taxafunc_ploter/heatmap_plot.py @@ -1,5 +1,9 @@ -from distinctipy import distinctipy +# for scaling data +import pandas as pd +from sklearn.preprocessing import StandardScaler +import numpy as np +# for heatmap plot import seaborn as sns import matplotlib.pyplot as plt from .get_distinct_colors import GetDistinctColors @@ -16,6 +20,7 @@ def __init__(self, tfobj, linkage_method:str = 'average', distance_metric:str = # EXAMPLE: plot_top_taxa_func_heatmap_of_test_res(df_anova, sw.func, 200, 'f', (30,30)) # reset sns style sns.set_theme() + plt.style.use('default') def rename_taxa(self, df): first_index = df.index[0] @@ -36,19 +41,23 @@ def plot_top_taxa_func_heatmap_of_test_res(self, df, top_number:int|str= 100, value_type:str = 'p', fig_size:tuple|None = None, pvalue:float = 0.05, col_cluster:bool = True, row_cluster:bool = True, cmap:str|None = None, rename_taxa:bool = True, font_size:int = 10, title:str = '', - show_all_labels:tuple = (False, False), return_type:str = 'fig'): + show_all_labels:tuple = (False, False), return_type:str = 'fig', scale = None, scale_method:str = 'maxmin'): func_name = self.tfa.func_name dft = df.copy() dft.reset_index(inplace=True) - type_map = {'f': ('f-statistic', 'Spectral_r', 1), - 'p': ('P-value', 'Reds_r', None), - 't': ('t-statistic', 'hot_r', 1)} + - plot_type = type_map.get(value_type, None)[0] - if plot_type is None: + + # type_map: 1st: plot_type, 2nd: cmap + type_map = {'f': ('f-statistic', 'Spectral_r'), + 'p': ('P-value', 'Reds_r'), + 't': ('t-statistic', 'RdBu_r')} + + plot_type = type_map.get(value_type, "None")[0] + if plot_type == "None": raise ValueError("type must be 'p' or 'f' or 't'") @@ -59,9 +68,9 @@ def plot_top_taxa_func_heatmap_of_test_res(self, df, top_number:int|str= 100, if cmap is None: - plot_type, cmap, scale = type_map.get(value_type, None) + plot_type, cmap = type_map.get(value_type, None) else: - plot_type, _, scale = type_map.get(value_type, None) + plot_type, _ = type_map.get(value_type, None) @@ -83,14 +92,14 @@ def plot_top_taxa_func_heatmap_of_test_res(self, df, top_number:int|str= 100, print(f"Top [{top_number}] significant: Taxa ({df_top.shape[1]}), Functions ({df_top.shape[0]})") df_plot = df_top.fillna(1) if plot_type == 'P-value' else df_top.fillna(0) - sns.set_style("white") + df_plot = self.scale_data(df = df_plot, scale_by = scale, method = scale_method) if return_type == 'fig': sns_params = { "center": 0, "cmap": cmap, - "linewidths": 0.2, - "linecolor": (0, 0, 0, 0.1), # last value is alpha value, 0 is transparent, 1 is opaque + "linewidths": 0.5, + "linecolor": 'gray', "dendrogram_ratio": (0.1, 0.2), "figsize": fig_size, "col_cluster": col_cluster, @@ -110,9 +119,9 @@ def plot_top_taxa_func_heatmap_of_test_res(self, df, top_number:int|str= 100, fig.ax_heatmap.set_xlabel("Taxa") fig.ax_heatmap.set_ylabel("Functions") if title == "": - title = f"Significant Differences between groups in Taxa-Function (Sorted by {plot_type} Top {top_number})" + title = f"Significant Differences between groups in Taxa-Function (Top {top_number} sorted by {plot_type} , scaled by {scale})" else: - title = f"{title} (Sorted by {plot_type} Top {top_number})" + title = f"{title} (Top {top_number} sorted by {plot_type} , scaled by {scale})" plt.suptitle(title, weight='bold') @@ -130,8 +139,8 @@ def plot_top_taxa_func_heatmap_of_test_res(self, df, top_number:int|str= 100, cbar = fig.ax_heatmap.collections[0].colorbar cbar.set_label(plot_type, rotation=90, labelpad=1) cbar.ax.yaxis.set_ticks_position('left') - cbar.ax.yaxis.set_label_position('left') - + cbar.ax.yaxis.set_label_position('right') + plt.subplots_adjust(left=0.06, bottom=0.35, right=0.5, top=0.96, wspace=0.01, hspace=0.01) plt.tight_layout() @@ -147,7 +156,6 @@ def plot_top_taxa_func_heatmap_of_test_res(self, df, top_number:int|str= 100, "row_cluster": row_cluster, "method": self.linkage_method, "metric": self.distance_metric, - "standard_scale": scale, "mask": df_top.isnull(), } fig = sns.clustermap(df_plot, **sns_params) @@ -179,20 +187,28 @@ def plot_basic_heatmap_of_test_res(self, df, top_number:int = 100, value_type:st fig_size:tuple|None = None, pvalue:float = 0.05, scale = None, col_cluster:bool = True, row_cluster:bool = True, cmap:str|None = None, rename_taxa:bool = True, font_size:int = 10, - show_all_labels:tuple = (False, False), rename_sample:bool = True + show_all_labels:tuple = (False, False), rename_sample:bool = True, + sort_by:str = 'P-value', scale_method:str = 'maxmin' ): dft = df.copy() + + scale_map ={None: None, + 'None': None, + 'row': 0, + 'column': 1} + scale = scale_map.get(scale) + scale_map ={None: None, 'None': None, 'row': 0, 'column': 1} scale = scale_map.get(scale) - type_map = {'f': ('f-statistic', 'Spectral_r'), - 'p': ('P-value', 'RdGy_r'), # Reds, hot_r were used before - 't': ('t-statistic', 'RdGy_r')} + type_map = {'f': ('f-statistic', 'Spectral_r' if scale_method == 'maxmin' else 'RdBu_r'), + 'p': ('P-value', 'RdGy_r' if scale_method == 'maxmin' else 'RdBu_r'), + 't': ('t-statistic', 'RdGy_r' if scale_method == 'maxmin' else 'RdBu_r')} if cmap is None: plot_type, cmap = type_map.get(value_type) @@ -210,14 +226,24 @@ def plot_basic_heatmap_of_test_res(self, df, top_number:int = 100, value_type:st dft = dft[dft['P-value'] < pvalue] - if 'f-statistic' in dft.columns.tolist(): - dft = dft.sort_values(by=['P-value', 'f-statistic'], ascending=[True, False]) - mat = dft.head(top_number) - mat= mat.drop(['P-value', 'f-statistic' ], axis=1) - elif 't-statistic' in dft.columns.tolist(): - dft = dft.sort_values(by=['P-value', 't-statistic'], ascending=[True, False]) - mat = dft.head(top_number) - mat= mat.drop(['P-value', 't-statistic'], axis=1) + if 'f-statistic' in dft.columns: + sort_column = 'f-statistic' if sort_by == 'f-statistic' else 'P-value' + ascending = sort_by == 'P-value' # True if sort_by is 'P-value' else False + dft = dft.sort_values(by=[sort_column], ascending=ascending) + mat = dft.head(top_number).drop(['P-value', 'f-statistic'], axis=1) + + elif 't-statistic' in dft.columns: + if sort_by == 't-statistic': + dft['abs_t-statistic'] = dft['t-statistic'].abs() + sort_column = 'abs_t-statistic' + ascending = False + else: + sort_column = 'P-value' + ascending = True + + dft = dft.sort_values(by=[sort_column], ascending=ascending) + mat = dft.head(top_number).drop(['P-value', 't-statistic', 'abs_t-statistic'], axis=1, errors='ignore') + else: raise ValueError("No 'f-statistic' or 't-statistic' in the dataframe") @@ -226,9 +252,6 @@ def plot_basic_heatmap_of_test_res(self, df, top_number:int = 100, value_type:st if len(mat.columns) < 2: col_cluster = False - meta_df = self.tfa.meta_df - meta_name = self.tfa.meta_name - if fig_size is None: fig_size = (30,30) @@ -244,6 +267,9 @@ def plot_basic_heatmap_of_test_res(self, df, top_number:int = 100, value_type:st if rename_taxa: mat = self.rename_taxa(mat) + + mat = self.scale_data(df = mat, scale_by = scale, method = scale_method) + sns_params = { "center": 0, "cmap": cmap, @@ -253,7 +279,6 @@ def plot_basic_heatmap_of_test_res(self, df, top_number:int = 100, value_type:st "row_cluster": row_cluster, "method": self.linkage_method, "metric": self.distance_metric, - "standard_scale": scale, "col_colors": color_list, "xticklabels": True if show_all_labels[0] else "auto", "yticklabels": True if show_all_labels[1] else "auto", @@ -264,13 +289,12 @@ def plot_basic_heatmap_of_test_res(self, df, top_number:int = 100, value_type:st fig.ax_heatmap.set_xticklabels(fig.ax_heatmap.get_xmajorticklabels(), fontsize=font_size, rotation=90) fig.ax_heatmap.set_yticklabels(fig.ax_heatmap.get_ymajorticklabels(), fontsize=font_size, rotation=0) plt.suptitle( - f"The Heatmap of intensity sorted by {plot_type} of Significant differences between groups (top {top_number})", - weight='bold' + f"The Heatmap of intensity of Significant differences between groups (top {top_number} sorted by {sort_by.split('(')[0]}, scaled by {scale})" ) cbar = fig.ax_heatmap.collections[0].colorbar cbar.set_label("Intensity", rotation=90, labelpad=1) cbar.ax.yaxis.set_ticks_position('left') - cbar.ax.yaxis.set_label_position('left') + cbar.ax.yaxis.set_label_position('right') plt.subplots_adjust(left=0.05, bottom=0.11, right=0.5, top=0.96, wspace=0.01, hspace=0.01) @@ -286,12 +310,12 @@ def plot_basic_heatmap_of_test_res(self, df, top_number:int = 100, value_type:st # Plot basic heatmap of matrix with color bar # EXAMPLE: plot_heatmap(sw, mat=get_top_intensity_matrix_of_test_res(df=df_anova, df_type='anova', top_num=100), # title = 'The heatmap of top 100 significant differences between groups in Taxa-Function', - # fig_size=(30,30), scale=0) + # fig_size=(30,30), scale='row') def plot_basic_heatmap(self, df, title = 'Heatmap',fig_size:tuple|None = None, scale = None, col_cluster:bool = True, row_cluster:bool = True, cmap:str|None = None, rename_taxa:bool = True, font_size:int = 10, show_all_labels:tuple = (False, False), rename_sample:bool = True, plot_mean:bool = False, - sub_meta: str = "None" + sub_meta: str = "None", scale_method:str = 'maxmin' ): ''' sub_meta is higher plot_mean, if sub_meta provided, plot_mean is False @@ -307,13 +331,9 @@ def plot_basic_heatmap(self, df, title = 'Heatmap',fig_size:tuple|None = None, if len(df.columns) < 2: col_cluster = False - scale_map ={None: None, - 'None': None, - 'row': 0, - 'column': 1} - scale = scale_map.get(scale) mat = df.copy() + mat = self.scale_data(df = mat, scale_by = scale, method = scale_method) # if index is Taxon, rename index if rename_taxa: @@ -332,7 +352,7 @@ def plot_basic_heatmap(self, df, title = 'Heatmap',fig_size:tuple|None = None, # if only one column, remove col_cluster, set scale to None if len(mat.columns) < 2: col_cluster = False - scale = None + # scale = None sns_params = { @@ -347,7 +367,6 @@ def plot_basic_heatmap(self, df, title = 'Heatmap',fig_size:tuple|None = None, "row_cluster": row_cluster, "method": self.linkage_method, "metric": self.distance_metric, - "standard_scale": scale, "col_colors": color_list if not plot_mean else None, "xticklabels": True if show_all_labels[0] else "auto", "yticklabels": True if show_all_labels[1] else "auto", @@ -358,13 +377,14 @@ def plot_basic_heatmap(self, df, title = 'Heatmap',fig_size:tuple|None = None, fig.ax_heatmap.set_xticklabels(fig.ax_heatmap.get_xmajorticklabels(), fontsize=font_size, rotation=90) fig.ax_heatmap.set_yticklabels(fig.ax_heatmap.get_ymajorticklabels(), fontsize=font_size, rotation=0) + title = f"{title} (scaled by {scale})" plt.suptitle(title, weight='bold') cbar = fig.ax_heatmap.collections[0].colorbar cbar.set_label('Intensity', rotation=90, labelpad=1) cbar.ax.yaxis.set_ticks_position('left') - cbar.ax.yaxis.set_label_position('left') - + cbar.ax.yaxis.set_label_position('right') + plt.subplots_adjust(left=0.05, bottom=0.15, right=0.5, top=0.96, wspace=0.01, hspace=0.01) plt.tight_layout() plt.show() @@ -374,9 +394,14 @@ def plot_basic_heatmap(self, df, title = 'Heatmap',fig_size:tuple|None = None, # For taxa-func heatmap # get the top intensity matrix of taxa-func table def get_top_across_table(self, df, top_number:str|int = 100, value_type:str = 'p', pvalue:float = 0.05, - rename_taxa:bool = False, col_cluster:bool = True, row_cluster:bool = True): + rename_taxa:bool = False, col_cluster:bool = True, row_cluster:bool = True, scale:str|None = None, scale_method:str = 'maxmin'): + ''' + For taxa-func table only + Return a table x, and y are taxa and functions, respectively, and the values are the p-value, f-statistic or t-statistic. + ''' res = self.plot_top_taxa_func_heatmap_of_test_res(df=df, top_number=top_number, value_type=value_type, pvalue=pvalue, - col_cluster=col_cluster, row_cluster=row_cluster, rename_taxa=rename_taxa, return_type='table') + col_cluster=col_cluster, row_cluster=row_cluster, rename_taxa=rename_taxa, return_type='table', + scale=scale, scale_method=scale_method) return res # plot heatmap for all condtion results of DESeq2All or DunnettAll @@ -386,7 +411,7 @@ def plot_heatmap_of_all_condition_res(self, df, pvalue:float = 0.05,scale:str|N show_all_labels:tuple = (False, False), return_type:str = 'fig', res_df_type:str = 'deseq2', p_type:str = 'padj', three_levels_df_type: str = 'same_trends', - show_col_colors:bool = True, remove_zero_col:bool = True): + show_col_colors:bool = True, remove_zero_col:bool = True, scale_method:str = 'maxmin'): """ Plot a heatmap of all condition results. @@ -419,7 +444,6 @@ def plot_heatmap_of_all_condition_res(self, df, pvalue:float = 0.05,scale:str|N - ValueError: If an error occurs during plotting. """ - import numpy as np # keep 4 decimal places pvalue = round(pvalue, 4) color_list = None @@ -476,7 +500,7 @@ def plot_heatmap_of_all_condition_res(self, df, pvalue:float = 0.05,scale:str|N dft = self.rename_taxa(dft) # scale the data if scale: - dft = self.scale_data(dft, scale) + dft = self.scale_data(df = dft, scale_by = scale, method = scale_method) if cmap is None: cmap = sns.color_palette("vlag", as_cmap=True, n_colors=30) @@ -524,8 +548,8 @@ def plot_heatmap_of_all_condition_res(self, df, pvalue:float = 0.05,scale:str|N cbar.set_label("log2FC" if res_df_type == 'deseq2' else 't-statistic', rotation=90, labelpad=1) cbar.ax.yaxis.set_ticks_position('left') - cbar.ax.yaxis.set_label_position('left') - + cbar.ax.yaxis.set_label_position('right') + plt.subplots_adjust(left=0.05, bottom=0.15, right=0.5, top=0.96, wspace=0.01, hspace=0.01) plt.tight_layout() @@ -568,11 +592,10 @@ def plot_heatmap_of_all_condition_res(self, df, pvalue:float = 0.05,scale:str|N def plot_heatmap_of_dunnett_test_res(self, df, pvalue:float = 0.05,scale:str|None = None, fig_size:tuple|None = None, col_cluster:bool = True, row_cluster:bool = True, cmap:str|None = None, rename_taxa:bool = True, font_size:int = 10, - show_all_labels:tuple = (False, False), show_col_colors:bool = False + show_all_labels:tuple = (False, False), show_col_colors:bool = False, scale_method:str = 'maxmin' ): #! 只画t-statistic的heatmap, 用p-value过滤 - import pandas as pd - import numpy as np + pvalue = round(pvalue, 5) @@ -609,7 +632,7 @@ def plot_heatmap_of_dunnett_test_res(self, df, pvalue:float = 0.05,scale:str|No # scale the data if scale: - dft = self.scale_data(dft, scale) + dft = self.scale_data(df = dft, scale_by = scale, method = scale_method) if cmap is None: @@ -647,8 +670,8 @@ def plot_heatmap_of_dunnett_test_res(self, df, pvalue:float = 0.05,scale:str|No cbar = fig.ax_heatmap.collections[0].colorbar cbar.set_label('t-statistic', rotation=90, labelpad=1) cbar.ax.yaxis.set_ticks_position('left') - cbar.ax.yaxis.set_label_position('left') - + cbar.ax.yaxis.set_label_position('right') + plt.subplots_adjust(left=0.05, bottom=0.15, right=0.5, top=0.96, wspace=0.01, hspace=0.01) plt.tight_layout() @@ -661,31 +684,8 @@ def plot_heatmap_of_dunnett_test_res(self, df, pvalue:float = 0.05,scale:str|No def get_heatmap_table_of_dunnett_res(self, df, pvalue:float = 0.05,scale:str|None = None, - col_cluster:bool = True, row_cluster:bool = True, rename_taxa:bool = True): - import pandas as pd - import numpy as np - - def scale_data(dft, scale): - if scale == 'row': - # 对每行单独应用双向缩放 - for index, row in dft.iterrows(): - max_val = abs(row).max() - if max_val != 0: - dft.loc[index] = row / max_val - elif scale == 'col': - # 对每列单独应用双向缩放 - for col in dft: - max_val = abs(dft[col]).max() - if max_val != 0: - dft[col] = dft[col] / max_val - elif scale == 'all': - # 对整个数据框应用双向缩放 - max_val = abs(dft.values).max() - if max_val != 0: - dft = dft / max_val - - return dft - + col_cluster:bool = True, row_cluster:bool = True, rename_taxa:bool = True, scale_method:str = 'maxmin'): + dft = self.tfa.CrossTest.extrcat_significant_stat_from_dunnett(df, p_value=pvalue) @@ -715,7 +715,7 @@ def scale_data(dft, scale): # scale the data if scale: - dft = scale_data(dft, scale) + dft = self.scale_data(df = dft, scale_by = scale, method = scale_method) from matplotlib.colors import TwoSlopeNorm @@ -754,14 +754,15 @@ def scale_data(dft, scale): def get_top_across_table_basic(self, df, top_number:int = 100, value_type:str = 'p', fig_size:tuple|None = None, pvalue:float = 0.05, scale = None, - col_cluster:bool = True, row_cluster:bool = True, cmap:str|None = None, rename_taxa:bool = False): + col_cluster:bool = True, row_cluster:bool = True, cmap:str|None = None, rename_taxa:bool = False, + scale_method:str = 'maxmin'): + ''' + for the tables of taxa, func, protein, peptides and custom table + Return a intensity matrix of top significant results. + ''' dft = df.copy() + - scale_map ={None: None, - 'None': None, - 'row': 0, - 'column': 1} - scale = scale_map.get(scale) type_map = {'f': ('f-statistic', 'Spectral_r'), 'p': ('P-value', 'Reds_r'), @@ -788,6 +789,7 @@ def get_top_across_table_basic(self, df, top_number:int = 100, value_type:str = mat = dft.head(top_number) mat= mat.drop(['P-value', 'f-statistic' ], axis=1) elif 't-statistic' in dft.columns.tolist(): + #! t-statistic incude positive and negative value dft = dft.sort_values(by=['P-value', 't-statistic'], ascending=[True, False]) mat = dft.head(top_number) mat= mat.drop(['P-value', 't-statistic'], axis=1) @@ -797,8 +799,10 @@ def get_top_across_table_basic(self, df, top_number:int = 100, value_type:str = if len(mat.columns) < 2: col_cluster = False - meta_df = self.tfa.meta_df - meta_name = self.tfa.meta_name + mat = self.scale_data(df = mat, scale_by = scale, method = scale_method) + + # meta_df = self.tfa.meta_df + # meta_name = self.tfa.meta_name if fig_size is None: @@ -812,8 +816,10 @@ def get_top_across_table_basic(self, df, top_number:int = 100, value_type:str = groups_list = [] new_col_names = [] for i in col_names: - group = meta_df[meta_df['Sample'] == i] - group = group[meta_name].values[0] + # group = meta_df[meta_df['Sample'] == i] + group = self.tfa.meta_df[self.tfa.meta_df['Sample'] == i] + # group = group[meta_name].values[0] + group = group[self.tfa.meta_name].values[0] new_col_names.append(f'{i} ({group})') groups_list.append(group) color_list = self.assign_colors(groups_list) @@ -831,7 +837,6 @@ def get_top_across_table_basic(self, df, top_number:int = 100, value_type:str = "row_cluster": row_cluster, "method": self.linkage_method, "metric": self.distance_metric, - "standard_scale": scale, "col_colors": color_list, } @@ -858,27 +863,83 @@ def get_top_across_table_basic(self, df, top_number:int = 100, value_type:str = # plt.close('all') - def scale_data(self, dft, scale): + + + def scale_data(self, df: pd.DataFrame, scale_by: str|None = None, method: str|None = 'maxmin') -> pd.DataFrame: + scale_by = scale_by.lower() if scale_by else 'all' + method = method.lower() if method else 'maxmin' + + print(f"Scaling the data by [{scale_by}] using method [{method}]") + try: - if scale == 'row': - # 对每行单独应用双向缩放 - for index, row in dft.iterrows(): - max_val = abs(row).max() - if max_val != 0: - dft.loc[index] = row / max_val - elif scale == 'col': - # 对每列单独应用双向缩放 - for col in dft: - max_val = abs(dft[col]).max() - if max_val != 0: - dft[col] = dft[col] / max_val - elif scale == 'all': - # 对整个数据框应用双向缩放 - max_val = abs(dft.values).max() - if max_val != 0: - dft = dft / max_val + if method == 'zscore': + scaler = StandardScaler() + + if scale_by == 'row': + if (df == 0).all(axis=1).any(): + raise ValueError("One or more rows are entirely zero, cannot perform z-score scaling.") + df = df.apply(lambda row: pd.Series(scaler.fit_transform(row.values.reshape(-1, 1)).flatten(), index=row.index), axis=1) + + elif scale_by == 'col': + if (df == 0).all(axis=0).any(): + raise ValueError("One or more columns are entirely zero, cannot perform z-score scaling.") + + df = df.apply(lambda col: pd.Series(scaler.fit_transform(col.values.reshape(-1, 1)).flatten(), index=col.index), axis=0) + + else: # 'all' + if np.all(df.values.flatten() == 0): + raise ValueError("All data are zero, cannot perform z-score scaling.") + + df = pd.DataFrame(scaler.fit_transform(df), index=df.index, columns=df.columns) + + else: # 'maxmin' + if scale_by == 'row': + max_val = df.abs().max(axis=1) + df = pd.DataFrame([row / max_val.loc[index] if max_val.loc[index] != 0 else row for index, row in df.iterrows()], index=df.index, columns=df.columns) + elif scale_by == 'col': + max_val = df.abs().max() + for col in df.columns: + if max_val[col] != 0: + df[col] = df[col] / max_val[col] + else: # 'all' + max_val = df.abs().values.max() + df = df / max_val if max_val != 0 else df + except Exception as e: - print(f'Error: {e}') + print(f'Error in scaling the data: {e}') + raise e + + return df + + + + # def scale_data(self, df, scale:str|None = None): + # '''' + # Scale the data by Max-Min scaling method + # ''' + # try: + # scale = scale.lower() if scale else None + + # print(f"Scaling the data by [{scale}]") + # if scale == 'row': + # for index, row in df.iterrows(): + # max_val = abs(row).max() + # if max_val != 0: + # df.loc[index] = row / max_val + # elif scale == 'col': + # for col in df: + # max_val = abs(df[col]).max() + # if max_val != 0: + # df[col] = df[col] / max_val + # elif scale == 'all': + # max_val = abs(df.values).max() + # if max_val != 0: + # df = df / max_val + # else: + # print('No scale applied') + + # except Exception as e: + # print(f'Error in scaling the data: {e}') - return dft + # return df diff --git a/metax/utils/version.py b/metax/utils/version.py index 6afbf81..e073248 100644 --- a/metax/utils/version.py +++ b/metax/utils/version.py @@ -1,2 +1,2 @@ -__version__ = '1.109.9' +__version__ = '1.109.10' API_version = '2' \ No newline at end of file