def multi_bar_raw(df="dataframe", dim=(5, 4), samp_col_name=None, bw=0.4, colorbar=None, r=300, show=False, axtickfontname="Arial", axtickfontsize=(9, 9), ax_x_ticklabel=None, ar=(0, 90), figtype='png', figname='multi_bar', valphabar=1, legendpos='best', errorbar=False, yerrlw=None, yerrcw=None, plotlegend=False, hbsize=4, ylm=None, add_sign_line=False, pv=None, sign_line_opts={'symbol': '*', 'fontsize': 9, 'linewidth': 0.8, 'arrowstyle': '-', 'dist_y_pos': 2.5, 'dist_y_neg': 4.2}, add_sign_symbol=False, sign_symbol_opts={'symbol': '*', 'fontsize': 9, 'fontname':'Arial', 'rotation':0}, dotplot=False, dotplot_opts={'dotsize': 5, 'color':'#7d0013', 'valpha': 1, 'marker': 'o'}, sign_line_pairs=None, group_let_df=None, legendanchor=None, legendcols=1, legendfontsize=8, axylabel=None, axxlabel=None, symb_dist=None, axlabelfontsize=(9, 9), axlabelar=(0, 90), sub_cat=None, sub_cat_opts={'y_neg_dist': 3.5, 'fontsize': 9, 'fontname':'Arial'}, sub_cat_label_dist=None, legendlabelframe=False, div_fact=20, legend_columnspacing=None, add_text=None, theme=None): if samp_col_name is None or colorbar is None: raise ValueError('Invalid value for samp_col_name or colorbar options') if theme == 'dark': general.dark_bg() fig, ax = plt.subplots(figsize=dim) sample_list = df[samp_col_name].unique() # assert len(sample_list) >= 2, "number of bar should be atleast 2" df_mean = df.groupby(samp_col_name).mean().reset_index().set_index(samp_col_name).T df_sem = df.groupby(samp_col_name).sem().reset_index().set_index(samp_col_name).T colbar = sample_list colerrorbar = sample_list xbar = np.arange(df_mean.shape[0]) xbar_temp = xbar xbarcol = df_mean.index assert len(colbar) == len(colorbar), "number of color should be equivalent to number of column bars" df_melt = pd.melt(df.reset_index(), id_vars=[samp_col_name], value_vars=df_mean.index) variable_list = df_melt['variable'].unique() min_value = (0, min(df_mean.min()))[min(df_mean.min()) < 0] if colbar is not None: for i in range(len(colbar)): if errorbar: ax.bar(x=xbar_temp, height=df_mean[colbar[i]], yerr=df_sem[colerrorbar[i]], width=bw, color=colorbar[i], alpha=valphabar, capsize=hbsize, label=colbar[i], error_kw={'elinewidth': yerrlw, 'capthick': yerrcw}) xbar_temp = xbar_temp + bw else: ax.bar(x=xbar_temp, height=df_mean[colbar[i]], width=bw, color=colorbar[i], alpha=valphabar, label=colbar[i]) xbar_temp = xbar_temp + bw bw_fact = bw / 2 ax.set_xticks(xbar+((len(df_mean.columns)-1) * bw_fact) ) # ax.set_xticks(xbar + ((bw * (len(colbar) - 1)) / (1 + (len(colbar) - 1)))) if ax_x_ticklabel: x_ticklabel = ax_x_ticklabel else: x_ticklabel = df[xbarcol] ax.set_xticklabels(x_ticklabel, fontsize=axtickfontsize[0], rotation=ar[0], fontname=axtickfontname) if axylabel: ax.set_ylabel(axylabel, fontsize=axlabelfontsize[1], rotation=axlabelar[1], fontname=axtickfontname) if axxlabel: ax.set_xlabel(axxlabel, fontsize=axlabelfontsize[0], rotation=axlabelar[0], fontname=axtickfontname) # ylm must be tuple of start, end, interval if ylm: plt.ylim(bottom=ylm[0], top=ylm[1]) plt.yticks(np.arange(ylm[0], ylm[1], ylm[2]), fontsize=axtickfontsize[1], fontname=axtickfontname) if plotlegend: plt.legend(loc=legendpos, bbox_to_anchor=legendanchor, ncol=legendcols, fontsize=legendfontsize, frameon=legendlabelframe, columnspacing=legend_columnspacing) if isinstance(add_text, list): plt.text(add_text[0], add_text[1], add_text[2], fontsize=9, fontfamily='Arial') if dotplot: for cols in range(len(variable_list)): move_fact = 0 for cols1 in range(len(sample_list)): ax.scatter(x=np.linspace(xbar[cols] - bw_fact + move_fact, xbar[cols] + bw_fact + move_fact, int(df.groupby(samp_col_name).count().loc[sample_list[cols1], variable_list[cols]])), y=df_melt[(df_melt['variable'] == df_melt['variable'].unique()[cols]) & ( df_melt[samp_col_name] == sample_list[cols1])]['value'], s=dotplot_opts['dotsize'], color=dotplot_opts['color'], zorder=10, alpha=dotplot_opts['valpha'], marker=dotplot_opts['marker']) move_fact += 2 * bw_fact size_factor_to_start_line = max(df_mean.max()) / div_fact y_pos_dict = dict() y_pos_dict_trt = dict() if add_sign_line: if len(colbar) == 2: for i in xbar: x_pos = xbar[i] x_pos_2 = xbar[i] + bw y_pos = df_mean[colbar[0]].to_numpy()[i] + df_sem[colerrorbar[0]].to_numpy()[i] y_pos_2 = df_mean[colbar[1]].to_numpy()[i] + df_sem[colerrorbar[1]].to_numpy()[i] # only if y axis is positive if y_pos > 0: y_pos += 0.5 y_pos_2 += 0.5 pv_symb = general.pvalue_symbol(pv[i], sign_line_opts['symbol']) if pv_symb: ax.annotate('', xy=(x_pos, max(y_pos, y_pos_2)), xytext=(x_pos_2, max(y_pos, y_pos_2)), arrowprops={'connectionstyle': 'bar, armA=50, armB=50, angle=180, fraction=0 ', 'arrowstyle': sign_line_opts['arrowstyle'], 'linewidth': sign_line_opts['linewidth']}) ax.annotate(pv_symb, xy=(np.mean([x_pos, x_pos_2]), max(y_pos, y_pos_2) + sign_line_opts['dist_y_pos']), fontsize=sign_line_opts['fontsize'], ha="center") else: y_pos -= 0.5 y_pos_2 -= 0.5 pv_symb = general.pvalue_symbol(pv[i], sign_line_opts['symbol']) if pv_symb: ax.annotate('', xy=(x_pos, y_pos), xytext=(x_pos_2, y_pos), arrowprops={'connectionstyle': 'bar, armA=50, armB=50, angle=180, fraction=-1 ', 'arrowstyle': sign_line_opts['arrowstyle'], 'linewidth': sign_line_opts['linewidth']}) ax.annotate(pv_symb, xy=(np.mean([x_pos, x_pos_2]), min(y_pos_2, y_pos) - sign_line_opts['dist_y_neg']), fontsize=sign_line_opts['fontsize'], ha="center") elif len(colbar) == 3: for i in xbar: x_pos = xbar[i] x_pos_2 = xbar[i] + bw x_pos_3 = xbar[i] + (2 * bw) y_pos = df_mean[colbar[0]].to_numpy()[i] + df_sem[colerrorbar[0]].to_numpy()[i] y_pos_2 = df_mean[colbar[1]].to_numpy()[i] + df_sem[colerrorbar[1]].to_numpy()[i] y_pos_3 = df_mean[colbar[2]].to_numpy()[i] + df_sem[colerrorbar[2]].to_numpy()[i] # only if y axis is positive if y_pos > 0: y_pos += size_factor_to_start_line / 2 y_pos_2 += size_factor_to_start_line / 2 y_pos_3 += size_factor_to_start_line / 2 pv_symb1 = general.pvalue_symbol(pv[i][0], sign_line_opts['symbol']) pv_symb2 = general.pvalue_symbol(pv[i][1], sign_line_opts['symbol']) if pv_symb1: if max(y_pos, y_pos_2) >= y_pos_3: pass ax.annotate('', xy=(x_pos, max(y_pos, y_pos_2)), xytext=(x_pos_2, max(y_pos, y_pos_2)), arrowprops={'connectionstyle': 'bar, armA=50, armB=50, angle=180, fraction=0 ', 'arrowstyle': sign_line_opts['arrowstyle'], 'linewidth': sign_line_opts['linewidth']}) ax.annotate(pv_symb1, xy=(np.mean([x_pos, x_pos_2]), max(y_pos, y_pos_2) + size_factor_to_start_line), fontsize=sign_line_opts['fontsize'], ha="center") if pv_symb2: if max(y_pos, y_pos_3) < y_pos_2: y_pos_3 = y_pos_2 + (4 * size_factor_to_start_line) ax.annotate('', xy=(x_pos, max(y_pos, y_pos_3)), xytext=(x_pos_3, max(y_pos, y_pos_3)), arrowprops={'connectionstyle': 'bar, armA=50, armB=50, angle=180, fraction=0 ', 'arrowstyle': sign_line_opts['arrowstyle'], 'linewidth': sign_line_opts['linewidth']}) ax.annotate(pv_symb2, xy=(np.mean([x_pos, x_pos_3]), max(y_pos, y_pos_3) + size_factor_to_start_line), fontsize=sign_line_opts['fontsize'], ha="center") else: y_pos -= 0.5 y_pos_2 -= 0.5 pv_symb = general.pvalue_symbol(pv[i], sign_line_opts['symbol']) if pv_symb: ax.annotate('', xy=(x_pos, y_pos), xytext=(x_pos_2, y_pos), arrowprops={'connectionstyle': 'bar, armA=50, armB=50, angle=180, fraction=-1 ', 'arrowstyle': sign_line_opts['arrowstyle'], 'linewidth': sign_line_opts['linewidth']}) ax.annotate(pv_symb, xy=(np.mean([x_pos, x_pos_2]), min(y_pos_2, y_pos) - sign_line_opts['dist_y_neg']), fontsize=sign_line_opts['fontsize'], ha="center") if add_sign_symbol: if len(colbar) == 2: for i in xbar: x_pos = xbar[i] x_pos_2 = xbar[i] + bw if symb_dist: # max value size factor is essential for rel pos of symbol y_pos = df_mean[colbar[0]].to_numpy()[i] + df_sem[colerrorbar[0]].to_numpy()[i] + \ (max(df_mean[colbar[0]].to_numpy()) / 20) + symb_dist[i][0] y_pos_2 = df_mean[colbar[1]].to_numpy()[i] + df_sem[colerrorbar[1]].to_numpy()[i] + \ (max(df_mean[colbar[1]].to_numpy()) / 20) + symb_dist[i][1] else: y_pos = df_mean[colbar[0]].to_numpy()[i] + df_sem[colerrorbar[0]].to_numpy()[i] + \ (max(df_mean[colbar[0]].to_numpy()) / 20) y_pos_2 = df_mean[colbar[1]].to_numpy()[i] + df_sem[colerrorbar[1]].to_numpy()[i] + \ (max(df_mean[colbar[1]].to_numpy()) / 20) ''' y_pos = df[colbar[0]].to_numpy()[i] + df[colerrorbar[0]].to_numpy()[i] + \ (max(df[colbar[0]].to_numpy()) / 20) y_pos_2 = df[colbar[1]].to_numpy()[i] + df[colerrorbar[1]].to_numpy()[i] + \ (max(df[colbar[1]].to_numpy()) / 20) ''' # group_let_df need index column if isinstance(group_let_df, pd.DataFrame): # only if y axis is positive if y_pos > 0: if not pd.isnull(group_let_df.loc[colbar[0], xbarcol[i]]): plt.annotate(group_let_df.loc[colbar[0], xbarcol[i]], xy=(x_pos, y_pos), fontsize=sign_symbol_opts['fontsize'], ha='center', fontfamily=sign_symbol_opts['fontname'], rotation=sign_symbol_opts['rotation']) if y_pos_2 > 0: if not pd.isnull(group_let_df.loc[colbar[1], xbarcol[i]]): plt.annotate(group_let_df.loc[colbar[1], xbarcol[i]], xy=(x_pos_2, y_pos_2), fontsize=sign_symbol_opts['fontsize'], ha='center', fontfamily=sign_symbol_opts['fontname'], rotation=sign_symbol_opts['rotation']) # only if y axis is positive # need to verify this elif pv: if y_pos > 0: pv_symb_1 = general.pvalue_symbol(pv[i][0], sign_symbol_opts['symbol']) pv_symb_2 = general.pvalue_symbol(pv[i][1], sign_symbol_opts['symbol']) if pv_symb_1: plt.annotate(pv_symb_1, xy=(x_pos, y_pos), fontsize=sign_symbol_opts['fontsize'], ha="center", fontfamily=sign_symbol_opts['fontname'], rotation=sign_symbol_opts['rotation']) if pv_symb_2: plt.annotate(pv_symb_2, xy=(x_pos_2, y_pos_2), fontsize=sign_symbol_opts['fontsize'], ha="center", fontfamily=sign_symbol_opts['fontname'], rotation=sign_symbol_opts['rotation']) else: raise Exception('Either group dataframe of p value list is required') elif len(colbar) == 3: for i in xbar: x_pos = xbar[i] x_pos_2 = xbar[i] + bw x_pos_3 = xbar[i] + (2 * bw) if symb_dist: # max value size factor is essential for rel pos of symbol y_pos = df_mean[colbar[0]].to_numpy()[i] + df_sem[colerrorbar[0]].to_numpy()[i] + \ (max(df_mean[colbar[0]].to_numpy()) / 20) + symb_dist[i][0] y_pos_2 = df_mean[colbar[1]].to_numpy()[i] + df_sem[colerrorbar[1]].to_numpy()[i] + \ (max(df_mean[colbar[1]].to_numpy()) / 20) + symb_dist[i][1] y_pos_3 = df_mean[colbar[2]].to_numpy()[i] + df_sem[colerrorbar[2]].to_numpy()[i] + \ (max(df_mean[colbar[2]].to_numpy()) / 20) + symb_dist[i][2] else: y_pos = df_mean[colbar[0]].to_numpy()[i] + df_sem[colerrorbar[0]].to_numpy()[i] + \ (max(df_mean[colbar[0]].to_numpy()) / 20) y_pos_2 = df_mean[colbar[1]].to_numpy()[i] + df_sem[colerrorbar[1]].to_numpy()[i] + \ (max(df_mean[colbar[1]].to_numpy()) / 20) y_pos_3 = df_mean[colbar[2]].to_numpy()[i] + df_sem[colerrorbar[2]].to_numpy()[i] + \ (max(df_mean[colbar[2]].to_numpy()) / 20) # group_let_df need index column if isinstance(group_let_df, pd.DataFrame): if y_pos > 0: plt.annotate(group_let_df.loc[colbar[0], xbarcol[i]], xy=(x_pos, y_pos), fontsize=sign_symbol_opts['fontsize'], ha="center", fontfamily=sign_symbol_opts['fontname'], rotation=sign_symbol_opts['rotation']) if y_pos_2 > 0: plt.annotate(group_let_df.loc[colbar[1], xbarcol[i]], xy=(x_pos_2, y_pos_2), fontsize=sign_symbol_opts['fontsize'], ha="center", fontfamily=sign_symbol_opts['fontname'], rotation=sign_symbol_opts['rotation']) if y_pos_3 > 0: plt.annotate(group_let_df.loc[colbar[2], xbarcol[i]], xy=(x_pos_3, y_pos_3), fontsize=sign_symbol_opts['fontsize'], ha="center", fontfamily=sign_symbol_opts['fontname'], rotation=sign_symbol_opts['rotation']) if pv: # only if y axis is positive if y_pos > 0: pv_symb_1 = general.pvalue_symbol(pv[i][0], sign_symbol_opts['symbol']) pv_symb_2 = general.pvalue_symbol(pv[i][1], sign_symbol_opts['symbol']) pv_symb_3 = general.pvalue_symbol(pv[i][2], sign_symbol_opts['symbol']) if pv_symb_1: plt.annotate(pv_symb_1, xy=(x_pos, y_pos), fontsize=sign_symbol_opts['fontsize'], ha="center", fontfamily=sign_symbol_opts['fontname'], rotation=sign_symbol_opts['rotation']) if pv_symb_2: plt.annotate(pv_symb_2, xy=(x_pos_2, y_pos_2), fontsize=sign_symbol_opts['fontsize'], ha="center", fontfamily=sign_symbol_opts['fontname'], rotation=sign_symbol_opts['rotation']) if pv_symb_3: plt.annotate(pv_symb_3, xy=(x_pos_3, y_pos_3), fontsize=sign_symbol_opts['fontsize'], ha="center", fontfamily=sign_symbol_opts['fontname'], rotation=sign_symbol_opts['rotation']) elif len(colbar) == 4: for i in xbar: x_pos = xbar[i] x_pos_2 = xbar[i] + bw x_pos_3 = xbar[i] + (2 * bw) x_pos_4 = xbar[i] + (3 * bw) if symb_dist: # max value size factor is essential for rel pos of symbol y_pos = df_mean[colbar[0]].to_numpy()[i] + df_sem[colerrorbar[0]].to_numpy()[i] + \ (max(df_mean[colbar[0]].to_numpy()) / 20) + symb_dist[i][0] y_pos_2 = df_mean[colbar[1]].to_numpy()[i] + df_sem[colerrorbar[1]].to_numpy()[i] + \ (max(df_mean[colbar[1]].to_numpy()) / 20) + symb_dist[i][1] y_pos_3 = df_mean[colbar[2]].to_numpy()[i] + df_sem[colerrorbar[2]].to_numpy()[i] + \ (max(df_mean[colbar[2]].to_numpy()) / 20) + symb_dist[i][2] y_pos_4 = df_mean[colbar[3]].to_numpy()[i] + df_sem[colerrorbar[3]].to_numpy()[i] + \ (max(df_mean[colbar[3]].to_numpy()) / 20) + symb_dist[i][3] else: y_pos = df_mean[colbar[0]].to_numpy()[i] + df_sem[colerrorbar[0]].to_numpy()[i] + \ (max(df_mean[colbar[0]].to_numpy()) / 20) y_pos_2 = df_mean[colbar[1]].to_numpy()[i] + df_sem[colerrorbar[1]].to_numpy()[i] + \ (max(df_mean[colbar[1]].to_numpy()) / 20) y_pos_3 = df_mean[colbar[2]].to_numpy()[i] + df_sem[colerrorbar[2]].to_numpy()[i] + \ (max(df_mean[colbar[2]].to_numpy()) / 20) y_pos_4 = df_mean[colbar[3]].to_numpy()[i] + df_sem[colerrorbar[3]].to_numpy()[i] + \ (max(df_mean[colbar[3]].to_numpy()) / 20) # group_let_df need index column if isinstance(group_let_df, pd.DataFrame): # only if y axis is positive if y_pos > 0: plt.annotate(group_let_df.loc[colbar[0], xbarcol[i]], xy=(x_pos, y_pos), fontsize=sign_symbol_opts['fontsize'], ha="center", fontfamily=sign_symbol_opts['fontname'], rotation=sign_symbol_opts['rotation']) if y_pos_2 > 0: plt.annotate(group_let_df.loc[colbar[1], xbarcol[i]], xy=(x_pos_2, y_pos_2), fontsize=sign_symbol_opts['fontsize'], ha="center", fontfamily=sign_symbol_opts['fontname'], rotation=sign_symbol_opts['rotation']) if y_pos_3 > 0: plt.annotate(group_let_df.loc[colbar[2], xbarcol[i]], xy=(x_pos_3, y_pos_3), fontsize=sign_symbol_opts['fontsize'], ha="center", fontfamily=sign_symbol_opts['fontname'], rotation=sign_symbol_opts['rotation']) if y_pos_4 > 0: plt.annotate(group_let_df.loc[colbar[3], xbarcol[i]], xy=(x_pos_4, y_pos_4), fontsize=sign_symbol_opts['fontsize'], ha="center", fontfamily=sign_symbol_opts['fontname'], rotation=sign_symbol_opts['rotation']) # need to work on this for 4 bars if pv: pv_symb_1 = general.pvalue_symbol(pv[i][0], sign_symbol_opts['symbol']) pv_symb_2 = general.pvalue_symbol(pv[i][1], sign_symbol_opts['symbol']) pv_symb_3 = general.pvalue_symbol(pv[i][2], sign_symbol_opts['symbol']) pv_symb_4 = general.pvalue_symbol(pv[i][3], sign_symbol_opts['symbol']) if pv_symb_1: plt.annotate(pv_symb_1, xy=(x_pos, y_pos), fontsize=sign_symbol_opts['fontsize'], ha="center", fontfamily=sign_symbol_opts['fontname'], rotation=sign_symbol_opts['rotation']) if pv_symb_2: plt.annotate(pv_symb_2, xy=(x_pos_2, y_pos_2), fontsize=sign_symbol_opts['fontsize'], ha="center", fontfamily=sign_symbol_opts['fontname'], rotation=sign_symbol_opts['rotation']) if pv_symb_3: plt.annotate(pv_symb_3, xy=(x_pos_3, y_pos_3), fontsize=sign_symbol_opts['fontsize'], ha="center", fontfamily=sign_symbol_opts['fontname'], rotation=sign_symbol_opts['rotation']) if pv_symb_4: plt.annotate(pv_symb_4, xy=(x_pos_4, y_pos_4), fontsize=sign_symbol_opts['fontsize'], ha="center", fontfamily=sign_symbol_opts['fontname'], rotation=sign_symbol_opts['rotation']) elif len(colbar) == 5: for i in xbar: x_pos = xbar[i] x_pos_2 = xbar[i] + bw x_pos_3 = xbar[i] + (2 * bw) x_pos_4 = xbar[i] + (3 * bw) x_pos_5 = xbar[i] + (4 * bw) # max value size factor is essential for rel pos of symbol if symb_dist: y_pos = df_mean[colbar[0]].to_numpy()[i] + df_sem[colerrorbar[0]].to_numpy()[i] + \ (max(df_mean[colbar[0]].to_numpy()) / 20) + symb_dist[i][0] y_pos_2 = df_mean[colbar[1]].to_numpy()[i] + df_sem[colerrorbar[1]].to_numpy()[i] + \ (max(df_mean[colbar[1]].to_numpy()) / 20) + symb_dist[i][1] y_pos_3 = df_mean[colbar[2]].to_numpy()[i] + df_sem[colerrorbar[2]].to_numpy()[i] + \ (max(df_mean[colbar[2]].to_numpy()) / 20) + symb_dist[i][2] y_pos_4 = df_mean[colbar[3]].to_numpy()[i] + df_sem[colerrorbar[3]].to_numpy()[i] + \ (max(df_mean[colbar[3]].to_numpy()) / 20) + symb_dist[i][3] y_pos_5 = df_mean[colbar[4]].to_numpy()[i] + df_sem[colerrorbar[4]].to_numpy()[i] + \ (max(df_mean[colbar[4]].to_numpy()) / 20) + symb_dist[i][4] else: y_pos = df_mean[colbar[0]].to_numpy()[i] + df_sem[colerrorbar[0]].to_numpy()[i] + \ (max(df_mean[colbar[0]].to_numpy()) / 20) y_pos_2 = df_mean[colbar[1]].to_numpy()[i] + df_sem[colerrorbar[1]].to_numpy()[i] + \ (max(df_mean[colbar[1]].to_numpy()) / 20) y_pos_3 = df_mean[colbar[2]].to_numpy()[i] + df_sem[colerrorbar[2]].to_numpy()[i] + \ (max(df_mean[colbar[2]].to_numpy()) / 20) y_pos_4 = df_mean[colbar[3]].to_numpy()[i] + df_sem[colerrorbar[3]].to_numpy()[i] + \ (max(df_mean[colbar[3]].to_numpy()) / 20) y_pos_5 = df_mean[colbar[4]].to_numpy()[i] + df_sem[colerrorbar[4]].to_numpy()[i] + \ (max(df_mean[colbar[4]].to_numpy()) / 20) # group_let_df need index column if isinstance(group_let_df, pd.DataFrame): # only if y axis is positive if y_pos > 0: plt.annotate(group_let_df.loc[colbar[0], xbarcol[i]], xy=(x_pos, y_pos), fontsize=sign_symbol_opts['fontsize'], ha="center") if y_pos_2 > 0: plt.annotate(group_let_df.loc[colbar[1], xbarcol[i]], xy=(x_pos_2, y_pos_2), fontsize=sign_symbol_opts['fontsize'], ha="center") if y_pos_3 > 0: plt.annotate(group_let_df.loc[colbar[2], xbarcol[i]], xy=(x_pos_3, y_pos_3), fontsize=sign_symbol_opts['fontsize'], ha="center") if y_pos_4 > 0: plt.annotate(group_let_df.loc[colbar[3], xbarcol[i]], xy=(x_pos_4, y_pos_4), fontsize=sign_symbol_opts['fontsize'], ha="center") if y_pos_5 > 0: plt.annotate(group_let_df.loc[colbar[4], xbarcol[i]], xy=(x_pos_5, y_pos_5), fontsize=sign_symbol_opts['fontsize'], ha="center") # need to work on this for 4 bars if pv: pv_symb_1 = general.pvalue_symbol(pv[i][0], sign_symbol_opts['symbol']) pv_symb_2 = general.pvalue_symbol(pv[i][1], sign_symbol_opts['symbol']) pv_symb_3 = general.pvalue_symbol(pv[i][2], sign_symbol_opts['symbol']) if pv_symb_1: plt.annotate(pv_symb_1, xy=(x_pos, y_pos), fontsize=sign_symbol_opts['fontsize'], ha="center") if pv_symb_2: plt.annotate(pv_symb_2, xy=(x_pos_2, y_pos_2), fontsize=sign_symbol_opts['fontsize'], ha="center") if pv_symb_3: plt.annotate(pv_symb_3, xy=(x_pos_3, y_pos_3), fontsize=sign_symbol_opts['fontsize'], ha="center") sub_cat_i = 0 if sub_cat: if isinstance(sub_cat, dict): for k in sub_cat: if isinstance(k, tuple) and len(k) == 2: cat_x_pos, cat_y_pos, cat_x_pos_2 = k[0], min_value - \ (sub_cat_opts[ 'y_neg_dist'] * size_factor_to_start_line), k[1] plt.annotate('', xy=(cat_x_pos - (bw / 2), cat_y_pos), xytext=(cat_x_pos_2 + (bw / 2), cat_y_pos), arrowprops={'arrowstyle': '-', 'linewidth': 0.5}, annotation_clip=False) if sub_cat_label_dist and isinstance(sub_cat_label_dist, list): plt.annotate(sub_cat[k], xy=(np.mean([cat_x_pos, cat_x_pos_2]), cat_y_pos - size_factor_to_start_line - sub_cat_label_dist[ sub_cat_i]), ha="center", fontsize=sub_cat_opts['fontsize'], annotation_clip=False, fontfamily=sub_cat_opts['fontname']) sub_cat_i += 1 else: plt.annotate(sub_cat[k], xy=(np.mean([cat_x_pos, cat_x_pos_2]), cat_y_pos - size_factor_to_start_line), ha="center", fontsize=sub_cat_opts['fontsize'], annotation_clip=False, fontfamily=sub_cat_opts['fontname']) else: raise KeyError("Sub category keys must be tuple of size 2") general.get_figure(show, r, figtype, figname, theme)