diff --git a/src/dimet/config/analysis/method/abundance_plot.yaml b/src/dimet/config/analysis/method/abundance_plot.yaml index 9feaa2f..7c2a4b9 100644 --- a/src/dimet/config/analysis/method/abundance_plot.yaml +++ b/src/dimet/config/analysis/method/abundance_plot.yaml @@ -11,7 +11,7 @@ height_each_subfig: !!float 5.5 palette: 'pastel' x_text_modify_as: null # or a list of float, int or str, e.g ['0h', '4h'] or [0, 4] according to the x ticks -as_grid : False +as_grid : False # if True will work when few (<20) metabolites by compartment do_stripplot: True diff --git a/src/dimet/config/analysis/method/mean_enrichment_line_plot.yaml b/src/dimet/config/analysis/method/mean_enrichment_line_plot.yaml index 9a6642d..0f1cf0b 100644 --- a/src/dimet/config/analysis/method/mean_enrichment_line_plot.yaml +++ b/src/dimet/config/analysis/method/mean_enrichment_line_plot.yaml @@ -6,10 +6,24 @@ name: Generate Mean Enrichment line plots figure_format: svg color_lines_by: condition # condition|metabolite -palette_condition: muted # seaborn/matplotlib palette. Has effect if color_lines_by condition -palette_metabolite: auto_multi_color # auto_multi_color|PATH_TO_COLOR.csv. Has effect if color_lines_by metabolite +palette_condition: muted # a seaborn or matplotlib palette name. Has effect if color_lines_by condition +palette_metabolite: auto_multi_color # auto_multi_color|[or user defined key-value pairs, see below] Has effect if color_lines_by metabolite xaxis_title: Time # Days|Hours|Minutes|Seconds|Time ... alpha: 1 # 0 for transparent, 1 max intensity plot_grouped_by_dict : null # cell : 0 : [Cit, Iso-cit] will display both in same plane height_subplot: !!float 4.8 as_grid : False + +# - - keep deactivated below this line -- +# # example of palette_metabolite set as user defined key-value pairs : +#palette_metabolite: # missing metabolites will be internally set as gray +# Fumaric_acid: cadetblue +# Glycine: darkviolet +# L-Alanine: orangered +# L-Arginine: pink +# L-Asparagine: "#AFB83B" +# L-Aspartic_acid: "#FBF312" +# L-Glutamic_acid: "#FF8D85" +# L-Malic_acid: darkcyan + + diff --git a/src/dimet/method/__init__.py b/src/dimet/method/__init__.py index 8f66c40..f77014c 100644 --- a/src/dimet/method/__init__.py +++ b/src/dimet/method/__init__.py @@ -115,7 +115,7 @@ class MeanEnrichmentLinePlotConfig(MethodConfig): xaxis_title: str = "Time" color_lines_by: str = "condition" # or "metabolite" palette_condition: str = "paired" # seaborn/matplotlib pals - palette_metabolite: str = "auto_multi_color" # or .csv path + palette_metabolite: Union[str, dict] = "auto_multi_color" height_subplot: float = 4.3 as_grid: Union[bool, None] = False diff --git a/src/dimet/visualization/abundance_bars.py b/src/dimet/visualization/abundance_bars.py index 5fa7eb2..0ecd0e6 100644 --- a/src/dimet/visualization/abundance_bars.py +++ b/src/dimet/visualization/abundance_bars.py @@ -53,7 +53,6 @@ def plot_one_metabolite(df: pd.DataFrame, returns a single object of type matplotlib.axes with the individual metabolite plot """ - plt.rcParams.update({"font.size": 21}) sns.barplot( ax=curr_ax, x=axisx_var, @@ -120,7 +119,7 @@ def plot_abundance_bars_no_grid( output_directory, f"bars_{CO}_{selected_metabolites[k]}-{SMX}" f".{cfg.analysis.method.figure_format}") - + plt.rcParams.update({"font.size": 21}) fig_this_metabolite, axs_k = plt.subplots( nrows=1, ncols=1, figsize=(width_each_subfig, height_each_subfig)) @@ -129,6 +128,7 @@ def plot_abundance_bars_no_grid( cfg.analysis.method.palette, axs_k, cfg.analysis.method.do_stripplot) + axs_k = apply_advanced_param_custom_x_labs(cfg, axs_k) if k == 0: # collect the legend, which is same for any plot thehandles, thelabels = axs_k.get_legend_handles_labels() axs_k.legend_.remove() @@ -148,6 +148,17 @@ def plot_abundance_bars_no_grid( logger.info(f"Saved abundance plots in {output_directory}") +def apply_advanced_param_custom_x_labs(cfg, curr_axs): + if cfg.analysis.method.x_text_modify_as is not None: + xticks_text_l: list = cfg.analysis.method.x_text_modify_as + try: + xticks_text_l = [str(i) for i in xticks_text_l] + curr_axs.set_xticklabels(xticks_text_l) + except Exception as e: + print(e, "The argument 'x_text_modify_as' is incorrectly set") + return curr_axs + + def plot_as_grid_of_bars( piled_sel_df: pd.DataFrame, selected_metabolites: List[str], CO: str, SMX: str, @@ -166,7 +177,7 @@ def plot_as_grid_of_bars( corrector_factor = 0.7 total_height_grid = height_each_subfig * len(selected_metabolites) + \ (corrector_factor * 7 * len(selected_metabolites)) - + plt.rcParams.update({"font.size": 21}) fig, axs = plt.subplots( nrows=len(selected_metabolites), ncols=1, sharey=False, figsize=(width_each_subfig, total_height_grid)) @@ -182,13 +193,7 @@ def plot_as_grid_of_bars( axs[i], cfg.analysis.method.do_stripplot) - if cfg.analysis.method.x_text_modify_as is not None: - xticks_text_l: list = cfg.analysis.method.x_text_modify_as - try: - xticks_text_l = [str(i) for i in xticks_text_l] - axs[i].set_xticklabels(xticks_text_l) - except Exception as e: - print(e, "The argument 'x_text_modify_as' is incorrectly set") + axs[i] = apply_advanced_param_custom_x_labs(cfg, axs[i]) thehandles, thelabels = axs[-1].get_legend_handles_labels() for i in range(len(selected_metabolites)): diff --git a/src/dimet/visualization/distr_fit_plot.py b/src/dimet/visualization/distr_fit_plot.py index a5c055f..a2a5b95 100644 --- a/src/dimet/visualization/distr_fit_plot.py +++ b/src/dimet/visualization/distr_fit_plot.py @@ -176,5 +176,5 @@ def run_distr_fit_plot( run_dist_fit_plot_pairwise(df, dataset, cfg, comparison, test, out_file_path) # elif mode == "time_course": - # pass # not implemented to date, evaluate if worthed + # pass # not implemented to date, evaluate if worth it logger.info(f"saved plots to {out_plot_dir}") diff --git a/src/dimet/visualization/mean_enrichment_line_plot.py b/src/dimet/visualization/mean_enrichment_line_plot.py index 7d2ed78..934280a 100644 --- a/src/dimet/visualization/mean_enrichment_line_plot.py +++ b/src/dimet/visualization/mean_enrichment_line_plot.py @@ -123,21 +123,24 @@ def plot_one_metabolite(metabolite_name: str, If several metabolites in input dataframes, they will be plotted sharing axes in same plane. """ - sns.lineplot( - ax=axs_z, # starts in 1 (after the empty row index 0) - x="timenum", - y="Fractional Contribution (%)", - hue=color_lines_by, - style="condition", - err_style=None, - alpha=alpha_conf, - linewidth=4.5, - palette=palette_option[color_lines_by], - zorder=1, - data=metabolite_df, - - legend=True, - ) + if len(list(metabolite_df['timenum'].unique())) > 1: + sns.lineplot( + ax=axs_z, # starts in 1 (after the empty row index 0) + x="timenum", y="Fractional Contribution (%)", + hue=color_lines_by, + style="condition", + err_style=None, + alpha=alpha_conf, + linewidth=4.5, + palette=palette_option[color_lines_by], + zorder=1, data=metabolite_df, + legend=True) + else: # when only one time point line is impossible, do scatter (dots) + sns.scatterplot( + ax=axs_z, x="timenum", y="Fractional Contribution (%)", + hue=color_lines_by, style="condition", alpha=alpha_conf, s=40, + palette=palette_option[color_lines_by], zorder=1, legend=True, + data=metabolite_df) axs_z.set_xticks([float(i) for i in time_ticks]) axs_z.scatter( @@ -149,10 +152,7 @@ def plot_one_metabolite(metabolite_name: str, mean_and_sd_metabolite_df["timenum"], mean_and_sd_metabolite_df["mean"], yerr=mean_and_sd_metabolite_df["sd"], - fmt="none", - capsize=3.5, - ecolor="black", - zorder=2 + fmt="none", capsize=3.5, ecolor="black", zorder=2 ) axs_z.set_ylabel("Fractional Contribution (%)", size=19), axs_z.set(xlabel=xaxis_title) @@ -300,34 +300,48 @@ def give_colors_by_metabolite(cfg: DictConfig, "mediumturquoise", "darkcyan", "teal", "cadetblue", "slategrey", "steelblue", "navy", "darkslateblue", "blueviolet", - "darkochid", "purple", "mediumvioletred", "crimson"] + "darkorchid", "purple", "mediumvioletred", "crimson"] colors_dict = dict() + tmp = set() + for co in metabolites_numbered_dict.keys(): + for k in metabolites_numbered_dict[co].keys(): + tmp.update(set(metabolites_numbered_dict[co][k])) + metabolites = sorted(list(tmp)) + if cfg.analysis.method.palette_metabolite == "auto_multi_color": - tmp = set() - for co in metabolites_numbered_dict.keys(): - for k in metabolites_numbered_dict[co].keys(): - tmp.update(set(metabolites_numbered_dict[co][k])) - metabolites = sorted(list(tmp)) if len(metabolites) <= 12: # default Paired palette for coloring individual metabolites palettecols = sns.color_palette("Paired", 12) for i in range(len(metabolites)): colors_dict[metabolites[i]] = palettecols[i] - else: # more than 12 colors obliges to set them manually + elif (len(metabolites) > 12) and ( + len(metabolites) <= len(handycolors)): for i in range(len(metabolites)): colors_dict[metabolites[i]] = handycolors[i] - else: # argument_color_metabolites is a csv file + elif len(metabolites) > 30: + logger.error( + "Error: > %s metabolites: wrong combination of params " + " color_lines_by and palette_metabolite options. Please set " + "color_lines_by as 'condition'; or alternatively give key-" + "value pairs in palette_metabolite", (len(handycolors))) + raise ValueError + else: # argument_color_metabolites is a key-value dict (set in yaml) try: - file_containing_colors = cfg.analysis.method.palette_metabolite - df = pd.read_csv(file_containing_colors, header=0) - for i, row in df.iterrows(): - metabolite = df.iloc[i, 0] # first column metabolite - color = df.iloc[i, 1] # second column is color - colors_dict[metabolite] = color + # fill the user blanks with dimgray color by default + for metabolite in metabolites: + try: + colors_dict[metabolite] = ( + cfg.analysis.method.palette_metabolite[metabolite]) + except KeyError: + colors_dict[metabolite] = "dimgray" + except Exception as e: + colors_dict[metabolite] = "dimgray" + logger.info(e, "user color not readable, continuing") + except Exception as e: - logger.info(e, f"\n could not assign color, wrong csv file: \ + logger.info(e, f"\n could not assign color : \ {cfg.analysis.method.palette_metabolite}") colors_dict = None diff --git a/tests/test_abundance_bars.py b/tests/test_abundance_bars.py index 6d7096c..3bb761d 100644 --- a/tests/test_abundance_bars.py +++ b/tests/test_abundance_bars.py @@ -76,6 +76,7 @@ def test_plot_abundance_bars_no_grid(self): cfg_m = DictConfig({'analysis': { 'method': {'palette': 'dark', 'do_stripplot': False, + 'x_text_modify_as': None, 'figure_format': 'svg'} } })