diff --git a/Docs/ChangeLog.md b/Docs/ChangeLog.md index 056f480..3c4f9e9 100644 --- a/Docs/ChangeLog.md +++ b/Docs/ChangeLog.md @@ -1,3 +1,8 @@ +# Version: 1.106.0 +## Date: 2024-06-09 +### Changes: +- New: Added a parameter in Settting to enable user to set the linkages method and linkage distance for the heatmap plot.(removed some metrices due to when the data has zero, the linkage will raise error.) + # Version: 1.105.4 ## Date: 2024-06-05 ### Changes: diff --git a/Docs/example.ipynb b/Docs/example.ipynb index aa624a9..1075dbc 100644 --- a/Docs/example.ipynb +++ b/Docs/example.ipynb @@ -80,7 +80,24 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "et `function` and `multi tables` " + "Set `function` and `multi tables` \n", + "\n", + "\n", + "# set_multi_tables()\n", + "Sets multiple tables including Function table, Taxa table, and Taxa-Function table.\n", + "\n", + "Parameters:\n", + "- `level (str)`: The taxonomic level to consider. Default is 's' (species).\n", + "- `func_threshold (float)`: The threshold for function proportion. Default is 1.00.\n", + "- `processing_after_sum (bool)`: Whether to perform data preprocessing after summing protein intensity. Default is False.\n", + "- `data_preprocess_params (dict)`: Parameters for data preprocessing. Default is {'normalize_method': None, 'transform_method': None,\n", + " 'batch_meta': None, 'outlier_detect_method': None, 'outlier_handle_method': None,\n", + " 'outlier_detect_by_group': None, 'outlier_handle_by_group': None, 'processing_order': None}.\n", + "- `peptide_num_threshold (dict)`: Thresholds for peptide numbers in Function table, Taxa table, and Taxa-Function table.\n", + " Default is {'taxa': 1, 'func': 1, 'taxa_func': 1}.\n", + "- `sum_protein (bool)`: Whether to sum protein intensity. Default is False.\n", + "- `sum_protein_params (dict)`: Parameters for summing protein intensity. Default is {'method': 'razor', 'by_sample': False,\n", + " 'rank_method': 'unique_counts'}.\n" ] }, { @@ -401,7 +418,20 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Use the `get_df` method to get the Taxa, Function, OTFs, and Peptides tables" + "Use the `get_df` method to get the Taxa, Function, OTFs, and Peptides tables\n", + "Get the dataframe without peptide_num column\n", + "\n", + "### Parameters:\n", + "- table_name (str): The name of the table to retrieve. Valid options are:\n", + " - `peptide`: Returns the peptide_df table.\n", + " - `taxa`: Returns the taxa_df table.\n", + " - `func`: Returns the func_df table.\n", + " - `taxa_func`: Returns the taxa_func_df table.\n", + " - `func_taxa`: Returns the func_taxa_df table.\n", + " - `custom`: Returns the custom_df table.\n", + "\n", + "Returns:\n", + "- `pandas.DataFrame`\n" ] }, { diff --git a/utils/GUI.py b/utils/GUI.py index cc35fd6..3f831e7 100644 --- a/utils/GUI.py +++ b/utils/GUI.py @@ -156,6 +156,9 @@ def __init__(self, MainWindow): self.temp_params_dict = {} # 1.save the temp params for thread callback function 2.as a flag to check if the thread is running self.executors = [] # save all FunctionExecutor object self.add_theme_to_combobox() + + # ploting parameters + self.heatmap_params_dict = {'linkage_method': 'average', 'distance_metric': 'euclidean'} # set icon @@ -617,20 +620,21 @@ def show_settings_window(self): if self.settings_dialog is None: self.settings_dialog = QDialog(self.MainWindow) self.settings_dialog.setWindowTitle("Settings") - self.settings_dialog.setModal(True) + self.settings_dialog.setModal(False) layout = QVBoxLayout(self.settings_dialog) - # reszie the settings dialog self.settings_dialog.resize(600, 400) settings_widget = SettingsWidget(self.settings_dialog, self.update_branch, self.auto_check_update) settings_widget.update_mode_changed.connect(self.on_update_mode_changed) settings_widget.auto_check_update_changed.connect(self.on_auto_check_update_changed) - + settings_widget.heatmap_params_dict_changed.connect(self.on_heatmap_params_changed) + layout.addWidget(settings_widget) self.settings_dialog.setLayout(layout) - self.settings_dialog.exec_() - + self.settings_dialog.show() + + # handle the update mode changed from settings window def on_update_mode_changed(self, mode): self.update_branch = mode @@ -640,6 +644,11 @@ def on_update_mode_changed(self, mode): def on_auto_check_update_changed(self, auto_check): self.auto_check_update = auto_check print(f"Auto check update set to: {auto_check}") + + # handle the heatmap params changed from settings window + def on_heatmap_params_changed(self, params_dict): + self.heatmap_params_dict = params_dict + print(f"Heatmap params changed to: {params_dict}") ############### basic function End ############### @@ -3261,7 +3270,7 @@ def plot_basic_list(self, plot_type='heatmap'): # plot heatmap self.show_message(f'Plotting {plot_type}...') - HeatmapPlot(self.tfa).plot_basic_heatmap(df=df, title=title, fig_size=(int(width), int(height)), + HeatmapPlot(self.tfa, **self.heatmap_params_dict).plot_basic_heatmap(df=df, title=title, fig_size=(int(width), int(height)), scale=scale, row_cluster=row_cluster, col_cluster=col_cluster, cmap=cmap, rename_taxa=rename_taxa, font_size=font_size, show_all_labels=show_all_labels, rename_sample=rename_sample, @@ -4064,7 +4073,7 @@ def plot_top_heatmap(self): try: self.show_message(f'Plotting heatmap for {table_name}...') if table_name.startswith('dunnett_test'): - fig = HeatmapPlot(self.tfa).plot_heatmap_of_dunnett_test_res(df=df, + fig = HeatmapPlot(self.tfa, **self.heatmap_params_dict).plot_heatmap_of_dunnett_test_res(df=df, 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, @@ -4073,7 +4082,7 @@ def plot_top_heatmap(self): p_type = self.comboBox_top_heatmap_sort_type.currentText() three_levels_df_type = self.comboBox_cross_3_level_plot_df_type.currentText() - fig = HeatmapPlot(self.tfa).plot_heatmap_of_all_condition_res(df=df, res_df_type='deseq2', + fig = HeatmapPlot(self.tfa, **self.heatmap_params_dict).plot_heatmap_of_all_condition_res(df=df, res_df_type='deseq2', fig_size=fig_size, pvalue=pvalue, cmap=cmap, log2fc_min =self.doubleSpinBox_mini_log2fc_heatmap.value(), log2fc_max =self.doubleSpinBox_max_log2fc_heatmap.value(), @@ -4093,7 +4102,7 @@ def plot_top_heatmap(self): elif table_name.startswith('dunnettAllCondtion'): three_levels_df_type = self.comboBox_cross_3_level_plot_df_type.currentText() - fig = HeatmapPlot(self.tfa).plot_heatmap_of_all_condition_res(df=df, res_df_type='dunnett', + fig = HeatmapPlot(self.tfa, **self.heatmap_params_dict).plot_heatmap_of_all_condition_res(df=df, res_df_type='dunnett', 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, @@ -4126,13 +4135,13 @@ def plot_top_heatmap(self): title = "Functions Non-Significant; Related Taxa Significantly Different Across Groups" else: title = "" - fig = HeatmapPlot(self.tfa).plot_top_taxa_func_heatmap_of_test_res(df=df, + fig = HeatmapPlot(self.tfa, **self.heatmap_params_dict).plot_top_taxa_func_heatmap_of_test_res(df=df, 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) else: - fig = HeatmapPlot(self.tfa).plot_basic_heatmap_of_test_res(df=df, top_number=top_num, + 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, @@ -4169,12 +4178,12 @@ def get_top_cross_table(self): try: if table_name.startswith('dunnett_test'): - df_top_cross = HeatmapPlot(self.tfa).get_heatmap_table_of_dunnett_res(df = df, pvalue=pvalue,scale = scale, + 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) elif 'deseq2all' in table_name: p_type = self.comboBox_top_heatmap_sort_type.currentText() - df_top_cross = HeatmapPlot(self.tfa).plot_heatmap_of_all_condition_res(df = df, res_df_type='deseq2', + df_top_cross = HeatmapPlot(self.tfa, **self.heatmap_params_dict).plot_heatmap_of_all_condition_res(df = df, res_df_type='deseq2', pvalue=pvalue,scale = scale, log2fc_min =self.doubleSpinBox_mini_log2fc_heatmap.value(), log2fc_max =self.doubleSpinBox_max_log2fc_heatmap.value(), @@ -4184,7 +4193,7 @@ def get_top_cross_table(self): remove_zero_col = remove_zero_col ) elif 'dunnettAllCondtion' in table_name: - df_top_cross = HeatmapPlot(self.tfa).plot_heatmap_of_all_condition_res(df = df, res_df_type='dunnett', + df_top_cross = HeatmapPlot(self.tfa, **self.heatmap_params_dict).plot_heatmap_of_all_condition_res(df = df, res_df_type='dunnett', pvalue=pvalue,scale = scale, col_cluster = col_luster, row_cluster = row_luster, rename_taxa=rename_taxa, return_type = 'table', @@ -4195,12 +4204,12 @@ def get_top_cross_table(self): else: if 'taxa-functions' in table_name: - df_top_cross = HeatmapPlot(self.tfa).get_top_across_table(df=df, top_number=top_num, + 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: - df_top_cross = HeatmapPlot(self.tfa).get_top_across_table_basic(df=df, top_number=top_num, + 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) @@ -5107,7 +5116,7 @@ def plot_tflink_heatmap(self): try: self.show_message('Plotting heatmap, please wait...') - HeatmapPlot(self.tfa).plot_basic_heatmap(df=df, title=title, fig_size=(int(width), int(height)), + HeatmapPlot(self.tfa, **self.heatmap_params_dict).plot_basic_heatmap(df=df, title=title, fig_size=(int(width), int(height)), scale=scale, row_cluster=row_cluster, col_cluster=col_cluster, cmap=cmap, rename_taxa=rename_taxa, font_size=font_size, show_all_labels=show_all_labels, rename_sample=self.checkBox_tflink_hetatmap_rename_sample.isChecked(), plot_mean=plot_mean diff --git a/utils/MetaX_GUI/Setting.ui b/utils/MetaX_GUI/Setting.ui index 7bd996b..6e02d20 100644 --- a/utils/MetaX_GUI/Setting.ui +++ b/utils/MetaX_GUI/Setting.ui @@ -17,7 +17,7 @@ - 0 + 1 @@ -77,6 +77,137 @@ Others + + + + + HeatMap + + + + + + + + + Linkage Method + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + average + + + + average + + + + + single + + + + + complete + + + + + centroid + + + + + median + + + + + weighted + + + + + ward + + + + + + + + + + + + Linkage Metric + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + euclidean + + + + euclidean + + + + + chebyshev + + + + + cityblock + + + + + hamming + + + + + matching + + + + + minkowski + + + + + rogerstanimoto + + + + + russellrao + + + + + sqeuclidean + + + + + + + diff --git a/utils/MetaX_GUI/Settings.py b/utils/MetaX_GUI/Settings.py index 4e71687..3db7cd5 100644 --- a/utils/MetaX_GUI/Settings.py +++ b/utils/MetaX_GUI/Settings.py @@ -1,10 +1,11 @@ -from PyQt5.QtWidgets import QWidget +from PyQt5.QtWidgets import QWidget, QToolBox from PyQt5.QtCore import pyqtSignal from .Ui_Setting import Ui_Settings class SettingsWidget(QWidget): update_mode_changed = pyqtSignal(str) auto_check_update_changed = pyqtSignal(bool) + heatmap_params_dict_changed = pyqtSignal(dict) def __init__(self, parent=None, update_branch="main", auto_check_update=True): super().__init__(parent) @@ -21,9 +22,18 @@ def __init__(self, parent=None, update_branch="main", auto_check_update=True): # resize the window, 600x400 as default self.resize(600, 400) + # move to the first tab in QToolBox + toolbox = self.findChildren(QToolBox) + for widget in toolbox: + widget.setCurrentIndex(0) + + # signal-slot connections self.ui.checkBox_auto_check_update.stateChanged.connect(self.handle_checkbox_state_changed) self.ui.radioButton_update_stable.toggled.connect(self.handle_radio_button_toggled) self.ui.radioButton_update_beta.toggled.connect(self.handle_radio_button_toggled) + + self.ui.comboBox_heatmap_linkage_method.currentTextChanged.connect(self.handle_heatmap_params_changed) + self.ui.comboBox_heatmap_linkage_metric.currentTextChanged.connect(self.handle_heatmap_params_changed) def init_ui(self, update_mode, auto_check_update): if update_mode == "main": @@ -36,13 +46,16 @@ def handle_checkbox_state_changed(self): self.auto_check_update = self.ui.checkBox_auto_check_update.isChecked() self.auto_check_update_changed.emit(self.auto_check_update) - # def handle_radio_button_toggled(self): - # if self.ui.radioButton_update_stable.isChecked(): - # self.update_mode = "main" - # elif self.ui.radioButton_update_beta.isChecked(): - # self.update_mode = "dev" - # self.update_mode_changed.emit(self.update_mode) - + def handle_heatmap_params_changed(self): + method = self.ui.comboBox_heatmap_linkage_method.currentText() + metric = self.ui.comboBox_heatmap_linkage_metric.currentText() + + heatmap_params_dict = { + "linkage_method": method, + "distance_metric": metric + } + + self.heatmap_params_dict_changed.emit(heatmap_params_dict) def handle_radio_button_toggled(self, checked): sender = self.sender() diff --git a/utils/MetaX_GUI/Ui_Setting.py b/utils/MetaX_GUI/Ui_Setting.py index 1a58b53..fea7724 100644 --- a/utils/MetaX_GUI/Ui_Setting.py +++ b/utils/MetaX_GUI/Ui_Setting.py @@ -42,11 +42,52 @@ def setupUi(self, Settings): self.page_2 = QtWidgets.QWidget() self.page_2.setGeometry(QtCore.QRect(0, 0, 677, 333)) self.page_2.setObjectName("page_2") + self.gridLayout_4 = QtWidgets.QGridLayout(self.page_2) + self.gridLayout_4.setObjectName("gridLayout_4") + self.label = QtWidgets.QLabel(self.page_2) + self.label.setObjectName("label") + self.gridLayout_4.addWidget(self.label, 0, 0, 1, 1) + self.horizontalLayout = QtWidgets.QHBoxLayout() + self.horizontalLayout.setObjectName("horizontalLayout") + self.label_2 = QtWidgets.QLabel(self.page_2) + self.label_2.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter) + self.label_2.setObjectName("label_2") + self.horizontalLayout.addWidget(self.label_2) + self.comboBox_heatmap_linkage_method = QtWidgets.QComboBox(self.page_2) + self.comboBox_heatmap_linkage_method.setObjectName("comboBox_heatmap_linkage_method") + self.comboBox_heatmap_linkage_method.addItem("") + self.comboBox_heatmap_linkage_method.addItem("") + self.comboBox_heatmap_linkage_method.addItem("") + self.comboBox_heatmap_linkage_method.addItem("") + self.comboBox_heatmap_linkage_method.addItem("") + self.comboBox_heatmap_linkage_method.addItem("") + self.comboBox_heatmap_linkage_method.addItem("") + self.horizontalLayout.addWidget(self.comboBox_heatmap_linkage_method) + self.gridLayout_4.addLayout(self.horizontalLayout, 0, 1, 1, 1) + self.horizontalLayout_2 = QtWidgets.QHBoxLayout() + self.horizontalLayout_2.setObjectName("horizontalLayout_2") + self.label_3 = QtWidgets.QLabel(self.page_2) + self.label_3.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter) + self.label_3.setObjectName("label_3") + self.horizontalLayout_2.addWidget(self.label_3) + self.comboBox_heatmap_linkage_metric = QtWidgets.QComboBox(self.page_2) + self.comboBox_heatmap_linkage_metric.setObjectName("comboBox_heatmap_linkage_metric") + self.comboBox_heatmap_linkage_metric.addItem("") + self.comboBox_heatmap_linkage_metric.addItem("") + self.comboBox_heatmap_linkage_metric.addItem("") + self.comboBox_heatmap_linkage_metric.addItem("") + self.comboBox_heatmap_linkage_metric.addItem("") + self.comboBox_heatmap_linkage_metric.addItem("") + self.comboBox_heatmap_linkage_metric.addItem("") + self.comboBox_heatmap_linkage_metric.addItem("") + self.comboBox_heatmap_linkage_metric.addItem("") + self.horizontalLayout_2.addWidget(self.comboBox_heatmap_linkage_metric) + self.gridLayout_4.addLayout(self.horizontalLayout_2, 0, 2, 1, 1) self.toolBox.addItem(self.page_2, "") self.gridLayout.addWidget(self.toolBox, 0, 0, 1, 1) self.retranslateUi(Settings) - self.toolBox.setCurrentIndex(0) + self.toolBox.setCurrentIndex(1) QtCore.QMetaObject.connectSlotsByName(Settings) def retranslateUi(self, Settings): @@ -56,4 +97,25 @@ def retranslateUi(self, Settings): self.radioButton_update_stable.setText(_translate("Settings", "Stable")) self.radioButton_update_beta.setText(_translate("Settings", "Beta")) self.toolBox.setItemText(self.toolBox.indexOf(self.page), _translate("Settings", "General")) + self.label.setText(_translate("Settings", "HeatMap")) + 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")) + self.comboBox_heatmap_linkage_method.setItemText(1, _translate("Settings", "single")) + self.comboBox_heatmap_linkage_method.setItemText(2, _translate("Settings", "complete")) + self.comboBox_heatmap_linkage_method.setItemText(3, _translate("Settings", "centroid")) + self.comboBox_heatmap_linkage_method.setItemText(4, _translate("Settings", "median")) + self.comboBox_heatmap_linkage_method.setItemText(5, _translate("Settings", "weighted")) + self.comboBox_heatmap_linkage_method.setItemText(6, _translate("Settings", "ward")) + self.label_3.setText(_translate("Settings", "Linkage Metric")) + self.comboBox_heatmap_linkage_metric.setCurrentText(_translate("Settings", "euclidean")) + self.comboBox_heatmap_linkage_metric.setItemText(0, _translate("Settings", "euclidean")) + self.comboBox_heatmap_linkage_metric.setItemText(1, _translate("Settings", "chebyshev")) + self.comboBox_heatmap_linkage_metric.setItemText(2, _translate("Settings", "cityblock")) + self.comboBox_heatmap_linkage_metric.setItemText(3, _translate("Settings", "hamming")) + self.comboBox_heatmap_linkage_metric.setItemText(4, _translate("Settings", "matching")) + self.comboBox_heatmap_linkage_metric.setItemText(5, _translate("Settings", "minkowski")) + self.comboBox_heatmap_linkage_metric.setItemText(6, _translate("Settings", "rogerstanimoto")) + self.comboBox_heatmap_linkage_metric.setItemText(7, _translate("Settings", "russellrao")) + self.comboBox_heatmap_linkage_metric.setItemText(8, _translate("Settings", "sqeuclidean")) self.toolBox.setItemText(self.toolBox.indexOf(self.page_2), _translate("Settings", "Others")) diff --git a/utils/TaxaFuncPloter/basic_plot.py b/utils/TaxaFuncPloter/basic_plot.py index 1711f2d..ae748b3 100644 --- a/utils/TaxaFuncPloter/basic_plot.py +++ b/utils/TaxaFuncPloter/basic_plot.py @@ -370,6 +370,7 @@ def plot_corr_sns(self, df, title_name = 'Table', cluster = False, width=10, hei sns_params = {"linewidths":.01, "cmap":'coolwarm', "cbar_kws":{ "shrink": 0.5}, 'col_cluster':True if cluster else False, 'row_cluster':True if cluster else False, + 'method':'average', 'metric':'euclidean', "linecolor":(0/255, 0/255, 0/255, 0.01), "dendrogram_ratio":(.1, .2),"col_colors":color_list, "figsize":(width, height), "xticklabels":True if show_all_labels[0] else "auto", "yticklabels":True if show_all_labels[1] else 'auto'} diff --git a/utils/TaxaFuncPloter/heatmap_plot.py b/utils/TaxaFuncPloter/heatmap_plot.py index f9f090c..b43e935 100644 --- a/utils/TaxaFuncPloter/heatmap_plot.py +++ b/utils/TaxaFuncPloter/heatmap_plot.py @@ -5,10 +5,12 @@ from .get_distinct_colors import GetDistinctColors class HeatmapPlot: - def __init__(self, tfobj): + def __init__(self, tfobj, linkage_method:str = 'average', distance_metric:str = 'correlation'): self.tfa = tfobj self.get_distinct_colors = GetDistinctColors().get_distinct_colors self.assign_colors = GetDistinctColors().assign_colors + self.linkage_method = linkage_method + self.distance_metric = distance_metric # input: df, func_name, top_number, value_type, fig_size # EXAMPLE: plot_top_taxa_func_heatmap_of_test_res(df_anova, sw.func, 200, 'f', (30,30)) @@ -93,8 +95,8 @@ def plot_top_taxa_func_heatmap_of_test_res(self, df, top_number:int|str= 100, "figsize": fig_size, "col_cluster": col_cluster, "row_cluster": row_cluster, - "method": "average", - "metric": "correlation", + "method": self.linkage_method, + "metric": self.distance_metric, "cbar_kws": {"label": plot_type, "shrink": 0.5}, "standard_scale": scale, "mask": df_top.isnull(), @@ -143,8 +145,8 @@ def plot_top_taxa_func_heatmap_of_test_res(self, df, top_number:int|str= 100, "cmap": cmap, "col_cluster": col_cluster, "row_cluster": row_cluster, - "method": "average", - "metric": "correlation", + "method": self.linkage_method, + "metric": self.distance_metric, "standard_scale": scale, "mask": df_top.isnull(), } @@ -242,11 +244,20 @@ def plot_basic_heatmap_of_test_res(self, df, top_number:int = 100, value_type:st if rename_taxa: mat = self.rename_taxa(mat) - sns_params = {'center': 0, 'cmap': cmap, 'figsize': fig_size, - 'cbar_kws': {'label': 'Intensity',"shrink": 0.5}, - 'col_cluster': col_cluster, 'row_cluster': row_cluster, - '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"} + sns_params = { + "center": 0, + "cmap": cmap, + "figsize": fig_size, + "cbar_kws": {"label": "Intensity", "shrink": 0.5}, + "col_cluster": col_cluster, + "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", + } fig = sns.clustermap(mat, **sns_params) @@ -324,16 +335,28 @@ def plot_basic_heatmap(self, df, title = 'Heatmap',fig_size:tuple|None = None, if len(mat.columns) < 2: col_cluster = False scale = None - sns_params = {'center': 0, 'cmap': cmap, 'figsize': fig_size, - 'linewidths': .01, 'linecolor': (0/255, 0/255, 0/255, 0.01), "dendrogram_ratio":(.1, .2), - 'cbar_kws': {'label': 'Intensity',"shrink": 0.5}, 'col_cluster': col_cluster, 'row_cluster': row_cluster, - '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"} + + + sns_params = { + "center": 0, + "cmap": cmap, + "figsize": fig_size, + "linewidths": 0.01, + "linecolor": (0 / 255, 0 / 255, 0 / 255, 0.01), + "dendrogram_ratio": (0.1, 0.2), + "cbar_kws": {"label": "Intensity", "shrink": 0.5}, + "col_cluster": col_cluster, + "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", + } fig = sns.clustermap(mat, **sns_params) - # fig = sns.clustermap(mat, center=0, cmap = cmap ,figsize=fig_size, - # cbar_kws={'label': 'Intensity'}, col_cluster=col_cluster, row_cluster=row_cluster, - # standard_scale=scale, col_colors=color_list) + 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) @@ -465,15 +488,28 @@ def plot_heatmap_of_all_condition_res(self, df, pvalue:float = 0.05,scale:str|N vmax = np.max(np.abs(dft.values)) # 获取数据的最大绝对值 norm = TwoSlopeNorm(vmin=-vmax, vcenter=0, vmax=vmax) - sns_params = {'cmap': cmap, 'figsize': fig_size,'norm': norm,'linewidths': .01, - 'linecolor': (0/255, 0/255, 0/255, 0.01), "dendrogram_ratio":(.1, .2), - 'col_cluster': col_cluster, 'row_cluster': row_cluster, - 'cbar_kws': {"label":'log2FoldChange' if res_df_type == 'deseq2' else 't-statistic', - "shrink": 0.5}, - 'xticklabels':True if show_all_labels[0] else "auto", - "yticklabels":True if show_all_labels[1] else "auto", - "col_colors":color_list if show_col_colors else None} - + sns_params = { + "cmap": cmap, + "figsize": fig_size, + "norm": norm, + "linewidths": 0.01, + "linecolor": (0 / 255, 0 / 255, 0 / 255, 0.01), + "dendrogram_ratio": (0.1, 0.2), + "col_cluster": col_cluster, + "row_cluster": row_cluster, + "method": self.linkage_method, + "metric": self.distance_metric, + "cbar_kws": { + "label": "log2FoldChange" + if res_df_type == "deseq2" + else "t-statistic", + "shrink": 0.5, + }, + "xticklabels": True if show_all_labels[0] else "auto", + "yticklabels": True if show_all_labels[1] else "auto", + "col_colors": color_list if show_col_colors else None, + } + if return_type == 'fig': fig = sns.clustermap(dft, **sns_params) @@ -502,10 +538,15 @@ def plot_heatmap_of_all_condition_res(self, df, pvalue:float = 0.05,scale:str|N else: return fig elif return_type == 'table': - fig = sns.clustermap(dft, norm=norm, - col_cluster=col_cluster, row_cluster=row_cluster, - ) - + sns_params = { + "norm": norm, + "col_cluster": col_cluster, + "row_cluster": row_cluster, + "method": self.linkage_method, + "metric": self.distance_metric, + } + fig = sns.clustermap(dft, **sns_params) + # get the sorted dataframe if row_cluster and not col_cluster: sorted_df = dft.iloc[fig.dendrogram_row.reordered_ind, :] @@ -582,9 +623,22 @@ def plot_heatmap_of_dunnett_test_res(self, df, pvalue:float = 0.05,scale:str|No vmax = np.max(np.abs(dft.values)) # 获取数据的最大绝对值 norm = TwoSlopeNorm(vmin=-vmax, vcenter=0, vmax=vmax) - sns_params = {'cmap': cmap, 'figsize': fig_size,'norm': norm,'linewidths': .01, 'linecolor': (0/255, 0/255, 0/255, 0.01), "dendrogram_ratio":(.1, .2), - 'cbar_kws': {"label":'t-statistic', "shrink": 0.5}, 'col_cluster': col_cluster, 'row_cluster': row_cluster,"col_colors":col_colors if show_col_colors else None, - 'xticklabels':True if show_all_labels[0] else "auto", "yticklabels":True if show_all_labels[1] else "auto"} + sns_params = { + "cmap": cmap, + "figsize": fig_size, + "norm": norm, + "linewidths": 0.01, + "linecolor": (0 / 255, 0 / 255, 0 / 255, 0.01), + "dendrogram_ratio": (0.1, 0.2), + "cbar_kws": {"label": "t-statistic", "shrink": 0.5}, + "col_cluster": col_cluster, + "row_cluster": row_cluster, + "method": self.linkage_method, + "metric": self.distance_metric, + "col_colors": col_colors if show_col_colors else None, + "xticklabels": True if show_all_labels[0] else "auto", + "yticklabels": True if show_all_labels[1] else "auto", + } fig = sns.clustermap(dft, **sns_params) fig.ax_heatmap.set_xticklabels(fig.ax_heatmap.get_xmajorticklabels(), fontsize=font_size, rotation=90) @@ -669,13 +723,17 @@ def scale_data(dft, scale): from matplotlib.colors import TwoSlopeNorm vmax = np.max(np.abs(dft.values)) # 获取数据的最大绝对值 norm = TwoSlopeNorm(vmin=-vmax, vcenter=0, vmax=vmax) - - - fig = sns.clustermap(dft, norm=norm, - col_cluster=col_cluster, row_cluster=row_cluster, - cbar_kws = dict(label='t-statistic'), - ) - + + sns_params = { + "norm": norm, + "col_cluster": col_cluster, + "row_cluster": row_cluster, + "method": self.linkage_method, + "metric": self.distance_metric, + "cbar_kws": {"label": "t-statistic"}, + } + fig = sns.clustermap(dft, **sns_params) + # get the sorted dataframe if row_cluster and not col_cluster: sorted_df = dft.iloc[fig.dendrogram_row.reordered_ind, :] @@ -766,9 +824,20 @@ def get_top_across_table_basic(self, df, top_number:int = 100, value_type:str = if rename_taxa: mat = self.rename_taxa(mat) - fig = sns.clustermap(mat, center=0, cmap = cmap ,figsize=fig_size, - cbar_kws={'label': 'Intensity'}, col_cluster=col_cluster, row_cluster=row_cluster, - standard_scale=scale, col_colors=color_list) + sns_params = { + "center": 0, + "cmap": cmap, + "figsize": fig_size, + "cbar_kws": {"label": "Intensity"}, + "col_cluster": col_cluster, + "row_cluster": row_cluster, + "method": self.linkage_method, + "metric": self.distance_metric, + "standard_scale": scale, + "col_colors": color_list, + } + + fig = sns.clustermap(mat, **sns_params) # get the sorted dataframe if row_cluster and not col_cluster: diff --git a/utils/version.py b/utils/version.py index feb08c1..f0140c7 100644 --- a/utils/version.py +++ b/utils/version.py @@ -1,2 +1,2 @@ -__version__ = '1.105.4' +__version__ = '1.106.0' API_version = '1' \ No newline at end of file