DingWB / PyComplexHeatmap

PyComplexHeatmap: A Python package to plot complex heatmap (clustermap)
https://dingwb.github.io/PyComplexHeatmap/
MIT License
297 stars 32 forks source link

Question about the function of `row_split` or `col_split` #4

Closed faridrashidi closed 1 year ago

faridrashidi commented 1 year ago

It seems the functions of row_split and col_split are a bit weird. See the example below:

import pandas as pd
from PyComplexHeatmap import *
data = pd.DataFrame([[0,1],
                     [1,0],
                     [0,1],
                     [1,0],
                     [0,1]])
ClusterMapPlotter(data=data, linewidth=1, row_dendrogram=True, row_cluster=True)

After adding row_split=2, one should expect to see the first two rows in the above image separated from the rest three rows. However, it looks like this is not the case and ClusterMapPlotter returns something different.

import pandas as pd
from PyComplexHeatmap import *
data = pd.DataFrame([[0,1],
                     [1,0],
                     [0,1],
                     [1,0],
                     [0,1]])
ClusterMapPlotter(data=data, linewidth=1, row_dendrogram=True, row_cluster=True, row_split=2, row_split_gap=5)

Do you have any opinion on this?

DingWB commented 1 year ago

As you requested, I just added a parameter legend_hpad to control the space between the heatmap and the legend. You can reinstall and try it. BTW, I have also added the parameter legend_vpad to control the space between the top of legend_anchor (ax or ax_heatmap) and the first legend.

faridrashidi commented 1 year ago

Thanks! Both method and metric are set to default in the above examples, but the results are different when row_split is added. Does setting row_split to something other than None alter method and metric? If not, then the results of the above examples should remain unchanged.

DingWB commented 1 year ago

I have already fixed the bug about the clustering when row_split or col_split is not equal to None. In the updated version, I changed the parameter legend_pad to legend_hpad.

faridrashidi commented 1 year ago

Wow! Thank, that's even nicer. Quick question, when trying to rotate the xlabels using the following parameters I get an error of

ClusterMapPlotter(
....
xlabel_kws={"rotation_mode": "anchor", "ha": "right"},
xticklabels_kws={"labelrotation": 90},
)

TypeError: Got both 'ha' and 'horizontalalignment', which are aliases of one another

I want to rotate the xlabels 180 degree and aligned them accordingly.

DingWB commented 1 year ago

Did you try to replace ha with horizontalalignment? For the rotation, please refer to

row_ha = HeatmapAnnotation(label=anno_label(df_cols.Family, merge=True,rotation=45),
                           Family=anno_simple(df_cols.Family, legend=True,height=5),
                           Tissue=anno_simple(df_cols.Tissue,height=5),
                           label_side='top',
                           label_kws={'rotation':45,'rotation_mode':'anchor','color':'red'},
                           axis=0)
plt.figure(figsize=(4, 7))
cm = ClusterMapPlotter(data=df.T,left_annotation=row_ha,
                       show_rownames=False, show_colnames=True,col_names_side='top',
                       row_split=df_cols.Family, cmap='exp1', label='AUC',
                       rasterized=True, legend=True,
                       xticklabels_kws={'labelrotation':45,'labelcolor':'blue'})
plt.show()
faridrashidi commented 1 year ago

See this example:

import pandas as pd
from PyComplexHeatmap import *
data = pd.DataFrame([[0,1],
                     [1,0],
                     [0,1],
                     [1,0],
                     [0,1]], index=list('abcde'), columns=['column1', 'column2'])
ClusterMapPlotter(data=data, linewidth=1, row_dendrogram=True,
                  row_cluster=True, row_split=2, row_split_gap=5, show_colnames=True, show_rownames=True,
                  xticklabels_kws={'labelrotation':90,'labelcolor':'blue'})
DingWB commented 1 year ago

Please try labelrotation: -90`. Or you can also try 'horizontalalignment': right, and 'lablerotation': 90.

faridrashidi commented 1 year ago

I get an error when using horizontalalignment

ValueError: keyword horizontalalignment is not recognized; ...

import pandas as pd
from PyComplexHeatmap import *
data = pd.DataFrame([[0,1],
                     [1,0],
                     [0,1],
                     [1,0],
                     [0,1]], index=list('abcde'), columns=['column1', 'column2'])
ClusterMapPlotter(data=data, linewidth=1, row_dendrogram=True,
                  row_cluster=True, row_split=2, row_split_gap=5, show_colnames=True, show_rownames=True,
                  xticklabels_kws={'labelrotation':90,'labelcolor':'blue', 'horizontalalignment':'right'})
DingWB commented 1 year ago

I see. ha was hard coding in my script. You can only use 'labelrotation': -90 to do that.

faridrashidi commented 1 year ago

For ease of reading, I want the xlabels to be read from bottom to top. Using a -90 degree is backwards.

DingWB commented 1 year ago

But it would be complicated for a common user, they have to think about the different combinations of labelrotation and ha.

faridrashidi commented 1 year ago

Hmm.. I see, is there anyway to have it as a parameter but with a default value instead of being hard-coded?

DingWB commented 1 year ago

If you really want to do that, you can try the following code for now, and I will think about how to make it into a parameter without making it more complicated:

import pandas as pd
from PyComplexHeatmap import *
data = pd.DataFrame([[0,1],
                     [1,0],
                     [0,1],
                     [1,0],
                     [0,1]], index=list('abcde'), columns=['column1', 'column2'])
plt.figure()
cm=ClusterMapPlotter(data=data, linewidth=1, row_dendrogram=True,
                  row_cluster=True, row_split=2, row_split_gap=5, show_colnames=True, show_rownames=True,
                  xticklabels_kws={'labelrotation':90,'labelcolor':'blue'})
plt.setp(cm.heatmap_axes[-1,0].get_xticklabels(), rotation_mode='anchor', ha='right')
plt.show()

There is one thing you need to pay attention to is that if you want the xticklabels to be read from bottom to top, what if some label is very long and other are very short? Then it would look odd.