visualize_5_34.py 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434
  1. def multi_bar_raw(df="dataframe", dim=(5, 4), samp_col_name=None, bw=0.4, colorbar=None, r=300,
  2. show=False, axtickfontname="Arial", axtickfontsize=(9, 9), ax_x_ticklabel=None, ar=(0, 90), figtype='png',
  3. figname='multi_bar', valphabar=1, legendpos='best', errorbar=False, yerrlw=None, yerrcw=None,
  4. plotlegend=False, hbsize=4, ylm=None, add_sign_line=False, pv=None,
  5. sign_line_opts={'symbol': '*', 'fontsize': 9, 'linewidth': 0.8, 'arrowstyle': '-', 'dist_y_pos': 2.5,
  6. 'dist_y_neg': 4.2}, add_sign_symbol=False,
  7. sign_symbol_opts={'symbol': '*', 'fontsize': 9, 'fontname':'Arial', 'rotation':0},
  8. dotplot=False, dotplot_opts={'dotsize': 5, 'color':'#7d0013', 'valpha': 1, 'marker': 'o'},
  9. sign_line_pairs=None, group_let_df=None, legendanchor=None, legendcols=1, legendfontsize=8,
  10. axylabel=None, axxlabel=None, symb_dist=None, axlabelfontsize=(9, 9), axlabelar=(0, 90), sub_cat=None,
  11. sub_cat_opts={'y_neg_dist': 3.5, 'fontsize': 9, 'fontname':'Arial'}, sub_cat_label_dist=None,
  12. legendlabelframe=False, div_fact=20, legend_columnspacing=None, add_text=None, theme=None):
  13. if samp_col_name is None or colorbar is None:
  14. raise ValueError('Invalid value for samp_col_name or colorbar options')
  15. if theme == 'dark':
  16. general.dark_bg()
  17. fig, ax = plt.subplots(figsize=dim)
  18. sample_list = df[samp_col_name].unique()
  19. # assert len(sample_list) >= 2, "number of bar should be atleast 2"
  20. df_mean = df.groupby(samp_col_name).mean().reset_index().set_index(samp_col_name).T
  21. df_sem = df.groupby(samp_col_name).sem().reset_index().set_index(samp_col_name).T
  22. colbar = sample_list
  23. colerrorbar = sample_list
  24. xbar = np.arange(df_mean.shape[0])
  25. xbar_temp = xbar
  26. xbarcol = df_mean.index
  27. assert len(colbar) == len(colorbar), "number of color should be equivalent to number of column bars"
  28. df_melt = pd.melt(df.reset_index(), id_vars=[samp_col_name], value_vars=df_mean.index)
  29. variable_list = df_melt['variable'].unique()
  30. min_value = (0, min(df_mean.min()))[min(df_mean.min()) < 0]
  31. if colbar is not None:
  32. for i in range(len(colbar)):
  33. if errorbar:
  34. ax.bar(x=xbar_temp, height=df_mean[colbar[i]], yerr=df_sem[colerrorbar[i]], width=bw,
  35. color=colorbar[i], alpha=valphabar, capsize=hbsize, label=colbar[i],
  36. error_kw={'elinewidth': yerrlw, 'capthick': yerrcw})
  37. xbar_temp = xbar_temp + bw
  38. else:
  39. ax.bar(x=xbar_temp, height=df_mean[colbar[i]], width=bw, color=colorbar[i], alpha=valphabar,
  40. label=colbar[i])
  41. xbar_temp = xbar_temp + bw
  42. bw_fact = bw / 2
  43. ax.set_xticks(xbar+((len(df_mean.columns)-1) * bw_fact) )
  44. # ax.set_xticks(xbar + ((bw * (len(colbar) - 1)) / (1 + (len(colbar) - 1))))
  45. if ax_x_ticklabel:
  46. x_ticklabel = ax_x_ticklabel
  47. else:
  48. x_ticklabel = df[xbarcol]
  49. ax.set_xticklabels(x_ticklabel, fontsize=axtickfontsize[0], rotation=ar[0], fontname=axtickfontname)
  50. if axylabel:
  51. ax.set_ylabel(axylabel, fontsize=axlabelfontsize[1], rotation=axlabelar[1], fontname=axtickfontname)
  52. if axxlabel:
  53. ax.set_xlabel(axxlabel, fontsize=axlabelfontsize[0], rotation=axlabelar[0], fontname=axtickfontname)
  54. # ylm must be tuple of start, end, interval
  55. if ylm:
  56. plt.ylim(bottom=ylm[0], top=ylm[1])
  57. plt.yticks(np.arange(ylm[0], ylm[1], ylm[2]), fontsize=axtickfontsize[1],
  58. fontname=axtickfontname)
  59. if plotlegend:
  60. plt.legend(loc=legendpos, bbox_to_anchor=legendanchor, ncol=legendcols, fontsize=legendfontsize,
  61. frameon=legendlabelframe, columnspacing=legend_columnspacing)
  62. if isinstance(add_text, list):
  63. plt.text(add_text[0], add_text[1], add_text[2], fontsize=9, fontfamily='Arial')
  64. if dotplot:
  65. for cols in range(len(variable_list)):
  66. move_fact = 0
  67. for cols1 in range(len(sample_list)):
  68. ax.scatter(x=np.linspace(xbar[cols] - bw_fact + move_fact, xbar[cols] + bw_fact + move_fact,
  69. int(df.groupby(samp_col_name).count().loc[sample_list[cols1], variable_list[cols]])),
  70. y=df_melt[(df_melt['variable'] == df_melt['variable'].unique()[cols]) & (
  71. df_melt[samp_col_name] == sample_list[cols1])]['value'], s=dotplot_opts['dotsize'],
  72. color=dotplot_opts['color'], zorder=10, alpha=dotplot_opts['valpha'],
  73. marker=dotplot_opts['marker'])
  74. move_fact += 2 * bw_fact
  75. size_factor_to_start_line = max(df_mean.max()) / div_fact
  76. y_pos_dict = dict()
  77. y_pos_dict_trt = dict()
  78. if add_sign_line:
  79. if len(colbar) == 2:
  80. for i in xbar:
  81. x_pos = xbar[i]
  82. x_pos_2 = xbar[i] + bw
  83. y_pos = df_mean[colbar[0]].to_numpy()[i] + df_sem[colerrorbar[0]].to_numpy()[i]
  84. y_pos_2 = df_mean[colbar[1]].to_numpy()[i] + df_sem[colerrorbar[1]].to_numpy()[i]
  85. # only if y axis is positive
  86. if y_pos > 0:
  87. y_pos += 0.5
  88. y_pos_2 += 0.5
  89. pv_symb = general.pvalue_symbol(pv[i], sign_line_opts['symbol'])
  90. if pv_symb:
  91. ax.annotate('', xy=(x_pos, max(y_pos, y_pos_2)), xytext=(x_pos_2, max(y_pos, y_pos_2)),
  92. arrowprops={'connectionstyle': 'bar, armA=50, armB=50, angle=180, fraction=0 ',
  93. 'arrowstyle': sign_line_opts['arrowstyle'],
  94. 'linewidth': sign_line_opts['linewidth']})
  95. ax.annotate(pv_symb, xy=(np.mean([x_pos, x_pos_2]), max(y_pos, y_pos_2) +
  96. sign_line_opts['dist_y_pos']),
  97. fontsize=sign_line_opts['fontsize'], ha="center")
  98. else:
  99. y_pos -= 0.5
  100. y_pos_2 -= 0.5
  101. pv_symb = general.pvalue_symbol(pv[i], sign_line_opts['symbol'])
  102. if pv_symb:
  103. ax.annotate('', xy=(x_pos, y_pos), xytext=(x_pos_2, y_pos),
  104. arrowprops={'connectionstyle': 'bar, armA=50, armB=50, angle=180, fraction=-1 ',
  105. 'arrowstyle': sign_line_opts['arrowstyle'],
  106. 'linewidth': sign_line_opts['linewidth']})
  107. ax.annotate(pv_symb, xy=(np.mean([x_pos, x_pos_2]), min(y_pos_2, y_pos) -
  108. sign_line_opts['dist_y_neg']),
  109. fontsize=sign_line_opts['fontsize'], ha="center")
  110. elif len(colbar) == 3:
  111. for i in xbar:
  112. x_pos = xbar[i]
  113. x_pos_2 = xbar[i] + bw
  114. x_pos_3 = xbar[i] + (2 * bw)
  115. y_pos = df_mean[colbar[0]].to_numpy()[i] + df_sem[colerrorbar[0]].to_numpy()[i]
  116. y_pos_2 = df_mean[colbar[1]].to_numpy()[i] + df_sem[colerrorbar[1]].to_numpy()[i]
  117. y_pos_3 = df_mean[colbar[2]].to_numpy()[i] + df_sem[colerrorbar[2]].to_numpy()[i]
  118. # only if y axis is positive
  119. if y_pos > 0:
  120. y_pos += size_factor_to_start_line / 2
  121. y_pos_2 += size_factor_to_start_line / 2
  122. y_pos_3 += size_factor_to_start_line / 2
  123. pv_symb1 = general.pvalue_symbol(pv[i][0], sign_line_opts['symbol'])
  124. pv_symb2 = general.pvalue_symbol(pv[i][1], sign_line_opts['symbol'])
  125. if pv_symb1:
  126. if max(y_pos, y_pos_2) >= y_pos_3:
  127. pass
  128. ax.annotate('', xy=(x_pos, max(y_pos, y_pos_2)), xytext=(x_pos_2, max(y_pos, y_pos_2)),
  129. arrowprops={'connectionstyle': 'bar, armA=50, armB=50, angle=180, fraction=0 ',
  130. 'arrowstyle': sign_line_opts['arrowstyle'],
  131. 'linewidth': sign_line_opts['linewidth']})
  132. ax.annotate(pv_symb1, xy=(np.mean([x_pos, x_pos_2]), max(y_pos, y_pos_2) +
  133. size_factor_to_start_line),
  134. fontsize=sign_line_opts['fontsize'], ha="center")
  135. if pv_symb2:
  136. if max(y_pos, y_pos_3) < y_pos_2:
  137. y_pos_3 = y_pos_2 + (4 * size_factor_to_start_line)
  138. ax.annotate('', xy=(x_pos, max(y_pos, y_pos_3)), xytext=(x_pos_3, max(y_pos, y_pos_3)),
  139. arrowprops={'connectionstyle': 'bar, armA=50, armB=50, angle=180, fraction=0 ',
  140. 'arrowstyle': sign_line_opts['arrowstyle'],
  141. 'linewidth': sign_line_opts['linewidth']})
  142. ax.annotate(pv_symb2, xy=(np.mean([x_pos, x_pos_3]), max(y_pos, y_pos_3) +
  143. size_factor_to_start_line),
  144. fontsize=sign_line_opts['fontsize'], ha="center")
  145. else:
  146. y_pos -= 0.5
  147. y_pos_2 -= 0.5
  148. pv_symb = general.pvalue_symbol(pv[i], sign_line_opts['symbol'])
  149. if pv_symb:
  150. ax.annotate('', xy=(x_pos, y_pos), xytext=(x_pos_2, y_pos),
  151. arrowprops={'connectionstyle': 'bar, armA=50, armB=50, angle=180, fraction=-1 ',
  152. 'arrowstyle': sign_line_opts['arrowstyle'],
  153. 'linewidth': sign_line_opts['linewidth']})
  154. ax.annotate(pv_symb, xy=(np.mean([x_pos, x_pos_2]), min(y_pos_2, y_pos) -
  155. sign_line_opts['dist_y_neg']),
  156. fontsize=sign_line_opts['fontsize'], ha="center")
  157. if add_sign_symbol:
  158. if len(colbar) == 2:
  159. for i in xbar:
  160. x_pos = xbar[i]
  161. x_pos_2 = xbar[i] + bw
  162. if symb_dist:
  163. # max value size factor is essential for rel pos of symbol
  164. y_pos = df_mean[colbar[0]].to_numpy()[i] + df_sem[colerrorbar[0]].to_numpy()[i] + \
  165. (max(df_mean[colbar[0]].to_numpy()) / 20) + symb_dist[i][0]
  166. y_pos_2 = df_mean[colbar[1]].to_numpy()[i] + df_sem[colerrorbar[1]].to_numpy()[i] + \
  167. (max(df_mean[colbar[1]].to_numpy()) / 20) + symb_dist[i][1]
  168. else:
  169. y_pos = df_mean[colbar[0]].to_numpy()[i] + df_sem[colerrorbar[0]].to_numpy()[i] + \
  170. (max(df_mean[colbar[0]].to_numpy()) / 20)
  171. y_pos_2 = df_mean[colbar[1]].to_numpy()[i] + df_sem[colerrorbar[1]].to_numpy()[i] + \
  172. (max(df_mean[colbar[1]].to_numpy()) / 20)
  173. '''
  174. y_pos = df[colbar[0]].to_numpy()[i] + df[colerrorbar[0]].to_numpy()[i] + \
  175. (max(df[colbar[0]].to_numpy()) / 20)
  176. y_pos_2 = df[colbar[1]].to_numpy()[i] + df[colerrorbar[1]].to_numpy()[i] + \
  177. (max(df[colbar[1]].to_numpy()) / 20)
  178. '''
  179. # group_let_df need index column
  180. if isinstance(group_let_df, pd.DataFrame):
  181. # only if y axis is positive
  182. if y_pos > 0:
  183. if not pd.isnull(group_let_df.loc[colbar[0], xbarcol[i]]):
  184. plt.annotate(group_let_df.loc[colbar[0], xbarcol[i]], xy=(x_pos, y_pos),
  185. fontsize=sign_symbol_opts['fontsize'], ha='center',
  186. fontfamily=sign_symbol_opts['fontname'],
  187. rotation=sign_symbol_opts['rotation'])
  188. if y_pos_2 > 0:
  189. if not pd.isnull(group_let_df.loc[colbar[1], xbarcol[i]]):
  190. plt.annotate(group_let_df.loc[colbar[1], xbarcol[i]], xy=(x_pos_2, y_pos_2),
  191. fontsize=sign_symbol_opts['fontsize'], ha='center',
  192. fontfamily=sign_symbol_opts['fontname'],
  193. rotation=sign_symbol_opts['rotation'])
  194. # only if y axis is positive
  195. # need to verify this
  196. elif pv:
  197. if y_pos > 0:
  198. pv_symb_1 = general.pvalue_symbol(pv[i][0], sign_symbol_opts['symbol'])
  199. pv_symb_2 = general.pvalue_symbol(pv[i][1], sign_symbol_opts['symbol'])
  200. if pv_symb_1:
  201. plt.annotate(pv_symb_1, xy=(x_pos, y_pos), fontsize=sign_symbol_opts['fontsize'],
  202. ha="center", fontfamily=sign_symbol_opts['fontname'],
  203. rotation=sign_symbol_opts['rotation'])
  204. if pv_symb_2:
  205. plt.annotate(pv_symb_2, xy=(x_pos_2, y_pos_2), fontsize=sign_symbol_opts['fontsize'],
  206. ha="center", fontfamily=sign_symbol_opts['fontname'],
  207. rotation=sign_symbol_opts['rotation'])
  208. else:
  209. raise Exception('Either group dataframe of p value list is required')
  210. elif len(colbar) == 3:
  211. for i in xbar:
  212. x_pos = xbar[i]
  213. x_pos_2 = xbar[i] + bw
  214. x_pos_3 = xbar[i] + (2 * bw)
  215. if symb_dist:
  216. # max value size factor is essential for rel pos of symbol
  217. y_pos = df_mean[colbar[0]].to_numpy()[i] + df_sem[colerrorbar[0]].to_numpy()[i] + \
  218. (max(df_mean[colbar[0]].to_numpy()) / 20) + symb_dist[i][0]
  219. y_pos_2 = df_mean[colbar[1]].to_numpy()[i] + df_sem[colerrorbar[1]].to_numpy()[i] + \
  220. (max(df_mean[colbar[1]].to_numpy()) / 20) + symb_dist[i][1]
  221. y_pos_3 = df_mean[colbar[2]].to_numpy()[i] + df_sem[colerrorbar[2]].to_numpy()[i] + \
  222. (max(df_mean[colbar[2]].to_numpy()) / 20) + symb_dist[i][2]
  223. else:
  224. y_pos = df_mean[colbar[0]].to_numpy()[i] + df_sem[colerrorbar[0]].to_numpy()[i] + \
  225. (max(df_mean[colbar[0]].to_numpy()) / 20)
  226. y_pos_2 = df_mean[colbar[1]].to_numpy()[i] + df_sem[colerrorbar[1]].to_numpy()[i] + \
  227. (max(df_mean[colbar[1]].to_numpy()) / 20)
  228. y_pos_3 = df_mean[colbar[2]].to_numpy()[i] + df_sem[colerrorbar[2]].to_numpy()[i] + \
  229. (max(df_mean[colbar[2]].to_numpy()) / 20)
  230. # group_let_df need index column
  231. if isinstance(group_let_df, pd.DataFrame):
  232. if y_pos > 0:
  233. plt.annotate(group_let_df.loc[colbar[0], xbarcol[i]], xy=(x_pos, y_pos),
  234. fontsize=sign_symbol_opts['fontsize'], ha="center",
  235. fontfamily=sign_symbol_opts['fontname'], rotation=sign_symbol_opts['rotation'])
  236. if y_pos_2 > 0:
  237. plt.annotate(group_let_df.loc[colbar[1], xbarcol[i]], xy=(x_pos_2, y_pos_2),
  238. fontsize=sign_symbol_opts['fontsize'], ha="center",
  239. fontfamily=sign_symbol_opts['fontname'], rotation=sign_symbol_opts['rotation'])
  240. if y_pos_3 > 0:
  241. plt.annotate(group_let_df.loc[colbar[2], xbarcol[i]], xy=(x_pos_3, y_pos_3),
  242. fontsize=sign_symbol_opts['fontsize'], ha="center",
  243. fontfamily=sign_symbol_opts['fontname'], rotation=sign_symbol_opts['rotation'])
  244. if pv:
  245. # only if y axis is positive
  246. if y_pos > 0:
  247. pv_symb_1 = general.pvalue_symbol(pv[i][0], sign_symbol_opts['symbol'])
  248. pv_symb_2 = general.pvalue_symbol(pv[i][1], sign_symbol_opts['symbol'])
  249. pv_symb_3 = general.pvalue_symbol(pv[i][2], sign_symbol_opts['symbol'])
  250. if pv_symb_1:
  251. plt.annotate(pv_symb_1, xy=(x_pos, y_pos), fontsize=sign_symbol_opts['fontsize'],
  252. ha="center", fontfamily=sign_symbol_opts['fontname'],
  253. rotation=sign_symbol_opts['rotation'])
  254. if pv_symb_2:
  255. plt.annotate(pv_symb_2, xy=(x_pos_2, y_pos_2), fontsize=sign_symbol_opts['fontsize'],
  256. ha="center", fontfamily=sign_symbol_opts['fontname'],
  257. rotation=sign_symbol_opts['rotation'])
  258. if pv_symb_3:
  259. plt.annotate(pv_symb_3, xy=(x_pos_3, y_pos_3), fontsize=sign_symbol_opts['fontsize'],
  260. ha="center", fontfamily=sign_symbol_opts['fontname'],
  261. rotation=sign_symbol_opts['rotation'])
  262. elif len(colbar) == 4:
  263. for i in xbar:
  264. x_pos = xbar[i]
  265. x_pos_2 = xbar[i] + bw
  266. x_pos_3 = xbar[i] + (2 * bw)
  267. x_pos_4 = xbar[i] + (3 * bw)
  268. if symb_dist:
  269. # max value size factor is essential for rel pos of symbol
  270. y_pos = df_mean[colbar[0]].to_numpy()[i] + df_sem[colerrorbar[0]].to_numpy()[i] + \
  271. (max(df_mean[colbar[0]].to_numpy()) / 20) + symb_dist[i][0]
  272. y_pos_2 = df_mean[colbar[1]].to_numpy()[i] + df_sem[colerrorbar[1]].to_numpy()[i] + \
  273. (max(df_mean[colbar[1]].to_numpy()) / 20) + symb_dist[i][1]
  274. y_pos_3 = df_mean[colbar[2]].to_numpy()[i] + df_sem[colerrorbar[2]].to_numpy()[i] + \
  275. (max(df_mean[colbar[2]].to_numpy()) / 20) + symb_dist[i][2]
  276. y_pos_4 = df_mean[colbar[3]].to_numpy()[i] + df_sem[colerrorbar[3]].to_numpy()[i] + \
  277. (max(df_mean[colbar[3]].to_numpy()) / 20) + symb_dist[i][3]
  278. else:
  279. y_pos = df_mean[colbar[0]].to_numpy()[i] + df_sem[colerrorbar[0]].to_numpy()[i] + \
  280. (max(df_mean[colbar[0]].to_numpy()) / 20)
  281. y_pos_2 = df_mean[colbar[1]].to_numpy()[i] + df_sem[colerrorbar[1]].to_numpy()[i] + \
  282. (max(df_mean[colbar[1]].to_numpy()) / 20)
  283. y_pos_3 = df_mean[colbar[2]].to_numpy()[i] + df_sem[colerrorbar[2]].to_numpy()[i] + \
  284. (max(df_mean[colbar[2]].to_numpy()) / 20)
  285. y_pos_4 = df_mean[colbar[3]].to_numpy()[i] + df_sem[colerrorbar[3]].to_numpy()[i] + \
  286. (max(df_mean[colbar[3]].to_numpy()) / 20)
  287. # group_let_df need index column
  288. if isinstance(group_let_df, pd.DataFrame):
  289. # only if y axis is positive
  290. if y_pos > 0:
  291. plt.annotate(group_let_df.loc[colbar[0], xbarcol[i]], xy=(x_pos, y_pos),
  292. fontsize=sign_symbol_opts['fontsize'], ha="center",
  293. fontfamily=sign_symbol_opts['fontname'], rotation=sign_symbol_opts['rotation'])
  294. if y_pos_2 > 0:
  295. plt.annotate(group_let_df.loc[colbar[1], xbarcol[i]], xy=(x_pos_2, y_pos_2),
  296. fontsize=sign_symbol_opts['fontsize'], ha="center",
  297. fontfamily=sign_symbol_opts['fontname'], rotation=sign_symbol_opts['rotation'])
  298. if y_pos_3 > 0:
  299. plt.annotate(group_let_df.loc[colbar[2], xbarcol[i]], xy=(x_pos_3, y_pos_3),
  300. fontsize=sign_symbol_opts['fontsize'], ha="center",
  301. fontfamily=sign_symbol_opts['fontname'], rotation=sign_symbol_opts['rotation'])
  302. if y_pos_4 > 0:
  303. plt.annotate(group_let_df.loc[colbar[3], xbarcol[i]], xy=(x_pos_4, y_pos_4),
  304. fontsize=sign_symbol_opts['fontsize'], ha="center",
  305. fontfamily=sign_symbol_opts['fontname'], rotation=sign_symbol_opts['rotation'])
  306. # need to work on this for 4 bars
  307. if pv:
  308. pv_symb_1 = general.pvalue_symbol(pv[i][0], sign_symbol_opts['symbol'])
  309. pv_symb_2 = general.pvalue_symbol(pv[i][1], sign_symbol_opts['symbol'])
  310. pv_symb_3 = general.pvalue_symbol(pv[i][2], sign_symbol_opts['symbol'])
  311. pv_symb_4 = general.pvalue_symbol(pv[i][3], sign_symbol_opts['symbol'])
  312. if pv_symb_1:
  313. plt.annotate(pv_symb_1, xy=(x_pos, y_pos), fontsize=sign_symbol_opts['fontsize'],
  314. ha="center", fontfamily=sign_symbol_opts['fontname'],
  315. rotation=sign_symbol_opts['rotation'])
  316. if pv_symb_2:
  317. plt.annotate(pv_symb_2, xy=(x_pos_2, y_pos_2), fontsize=sign_symbol_opts['fontsize'],
  318. ha="center", fontfamily=sign_symbol_opts['fontname'],
  319. rotation=sign_symbol_opts['rotation'])
  320. if pv_symb_3:
  321. plt.annotate(pv_symb_3, xy=(x_pos_3, y_pos_3), fontsize=sign_symbol_opts['fontsize'],
  322. ha="center", fontfamily=sign_symbol_opts['fontname'],
  323. rotation=sign_symbol_opts['rotation'])
  324. if pv_symb_4:
  325. plt.annotate(pv_symb_4, xy=(x_pos_4, y_pos_4), fontsize=sign_symbol_opts['fontsize'],
  326. ha="center", fontfamily=sign_symbol_opts['fontname'],
  327. rotation=sign_symbol_opts['rotation'])
  328. elif len(colbar) == 5:
  329. for i in xbar:
  330. x_pos = xbar[i]
  331. x_pos_2 = xbar[i] + bw
  332. x_pos_3 = xbar[i] + (2 * bw)
  333. x_pos_4 = xbar[i] + (3 * bw)
  334. x_pos_5 = xbar[i] + (4 * bw)
  335. # max value size factor is essential for rel pos of symbol
  336. if symb_dist:
  337. y_pos = df_mean[colbar[0]].to_numpy()[i] + df_sem[colerrorbar[0]].to_numpy()[i] + \
  338. (max(df_mean[colbar[0]].to_numpy()) / 20) + symb_dist[i][0]
  339. y_pos_2 = df_mean[colbar[1]].to_numpy()[i] + df_sem[colerrorbar[1]].to_numpy()[i] + \
  340. (max(df_mean[colbar[1]].to_numpy()) / 20) + symb_dist[i][1]
  341. y_pos_3 = df_mean[colbar[2]].to_numpy()[i] + df_sem[colerrorbar[2]].to_numpy()[i] + \
  342. (max(df_mean[colbar[2]].to_numpy()) / 20) + symb_dist[i][2]
  343. y_pos_4 = df_mean[colbar[3]].to_numpy()[i] + df_sem[colerrorbar[3]].to_numpy()[i] + \
  344. (max(df_mean[colbar[3]].to_numpy()) / 20) + symb_dist[i][3]
  345. y_pos_5 = df_mean[colbar[4]].to_numpy()[i] + df_sem[colerrorbar[4]].to_numpy()[i] + \
  346. (max(df_mean[colbar[4]].to_numpy()) / 20) + symb_dist[i][4]
  347. else:
  348. y_pos = df_mean[colbar[0]].to_numpy()[i] + df_sem[colerrorbar[0]].to_numpy()[i] + \
  349. (max(df_mean[colbar[0]].to_numpy()) / 20)
  350. y_pos_2 = df_mean[colbar[1]].to_numpy()[i] + df_sem[colerrorbar[1]].to_numpy()[i] + \
  351. (max(df_mean[colbar[1]].to_numpy()) / 20)
  352. y_pos_3 = df_mean[colbar[2]].to_numpy()[i] + df_sem[colerrorbar[2]].to_numpy()[i] + \
  353. (max(df_mean[colbar[2]].to_numpy()) / 20)
  354. y_pos_4 = df_mean[colbar[3]].to_numpy()[i] + df_sem[colerrorbar[3]].to_numpy()[i] + \
  355. (max(df_mean[colbar[3]].to_numpy()) / 20)
  356. y_pos_5 = df_mean[colbar[4]].to_numpy()[i] + df_sem[colerrorbar[4]].to_numpy()[i] + \
  357. (max(df_mean[colbar[4]].to_numpy()) / 20)
  358. # group_let_df need index column
  359. if isinstance(group_let_df, pd.DataFrame):
  360. # only if y axis is positive
  361. if y_pos > 0:
  362. plt.annotate(group_let_df.loc[colbar[0], xbarcol[i]], xy=(x_pos, y_pos),
  363. fontsize=sign_symbol_opts['fontsize'], ha="center")
  364. if y_pos_2 > 0:
  365. plt.annotate(group_let_df.loc[colbar[1], xbarcol[i]], xy=(x_pos_2, y_pos_2),
  366. fontsize=sign_symbol_opts['fontsize'], ha="center")
  367. if y_pos_3 > 0:
  368. plt.annotate(group_let_df.loc[colbar[2], xbarcol[i]], xy=(x_pos_3, y_pos_3),
  369. fontsize=sign_symbol_opts['fontsize'], ha="center")
  370. if y_pos_4 > 0:
  371. plt.annotate(group_let_df.loc[colbar[3], xbarcol[i]], xy=(x_pos_4, y_pos_4),
  372. fontsize=sign_symbol_opts['fontsize'], ha="center")
  373. if y_pos_5 > 0:
  374. plt.annotate(group_let_df.loc[colbar[4], xbarcol[i]], xy=(x_pos_5, y_pos_5),
  375. fontsize=sign_symbol_opts['fontsize'], ha="center")
  376. # need to work on this for 4 bars
  377. if pv:
  378. pv_symb_1 = general.pvalue_symbol(pv[i][0], sign_symbol_opts['symbol'])
  379. pv_symb_2 = general.pvalue_symbol(pv[i][1], sign_symbol_opts['symbol'])
  380. pv_symb_3 = general.pvalue_symbol(pv[i][2], sign_symbol_opts['symbol'])
  381. if pv_symb_1:
  382. plt.annotate(pv_symb_1, xy=(x_pos, y_pos), fontsize=sign_symbol_opts['fontsize'],
  383. ha="center")
  384. if pv_symb_2:
  385. plt.annotate(pv_symb_2, xy=(x_pos_2, y_pos_2), fontsize=sign_symbol_opts['fontsize'],
  386. ha="center")
  387. if pv_symb_3:
  388. plt.annotate(pv_symb_3, xy=(x_pos_3, y_pos_3), fontsize=sign_symbol_opts['fontsize'],
  389. ha="center")
  390. sub_cat_i = 0
  391. if sub_cat:
  392. if isinstance(sub_cat, dict):
  393. for k in sub_cat:
  394. if isinstance(k, tuple) and len(k) == 2:
  395. cat_x_pos, cat_y_pos, cat_x_pos_2 = k[0], min_value - \
  396. (sub_cat_opts[
  397. 'y_neg_dist'] * size_factor_to_start_line), k[1]
  398. plt.annotate('', xy=(cat_x_pos - (bw / 2), cat_y_pos),
  399. xytext=(cat_x_pos_2 + (bw / 2), cat_y_pos),
  400. arrowprops={'arrowstyle': '-', 'linewidth': 0.5}, annotation_clip=False)
  401. if sub_cat_label_dist and isinstance(sub_cat_label_dist, list):
  402. plt.annotate(sub_cat[k], xy=(np.mean([cat_x_pos, cat_x_pos_2]),
  403. cat_y_pos - size_factor_to_start_line - sub_cat_label_dist[
  404. sub_cat_i]),
  405. ha="center", fontsize=sub_cat_opts['fontsize'], annotation_clip=False,
  406. fontfamily=sub_cat_opts['fontname'])
  407. sub_cat_i += 1
  408. else:
  409. plt.annotate(sub_cat[k], xy=(np.mean([cat_x_pos, cat_x_pos_2]),
  410. cat_y_pos - size_factor_to_start_line),
  411. ha="center", fontsize=sub_cat_opts['fontsize'], annotation_clip=False,
  412. fontfamily=sub_cat_opts['fontname'])
  413. else:
  414. raise KeyError("Sub category keys must be tuple of size 2")
  415. general.get_figure(show, r, figtype, figname, theme)