Marsilea-viz / marsilea

Declarative creation of composable visualization for Python (Complex heatmap, Upset plot, Oncoprint and more~)
https://marsilea.rtfd.io/
MIT License
166 stars 6 forks source link

truncated re-centred colorbar #38

Closed hmassalha closed 3 months ago

hmassalha commented 3 months ago

Hello, I have the following heatmap. I forced the colormap to be centered at value 0 using and it is working.

ma.Heatmap(df, linewidth=0.5, width=6, height=6, label="Mean\nscaled",
              norm = TwoSlopeNorm(vmin=df.min().min(), vcenter=0, vmax=df.max().max()))

image

However, with 'TwoSlopeNorm' the two sides of the values 0 are with different slopes, but the colorbar show symetric positioning of value 0. The min values is -1.9, while the max value is 4. I was wondering if can help me making the position of 0 more representative by controling the limits of the colorbar? Here is another output for MAtplotlib guide showing the same phenomica with using "TwoSlopeNorm" https://matplotlib.org/stable/users/explain/colors/colormapnorms.html#twoslopenorm-different-mapping-on-either-side-of-a-center

Many thanks, HM

Mr-Milk commented 3 months ago

If I understand correctly, you want to center on 0 with same slope on both side. You can set a symmetry vmin and vmax. For example, your data's min is -1.6 and max is 4, you can set vmin=-4 and vmax=4.

vmax = np.max(np.abs(data))
vmin = -vmax

I hope this solves your problem, feel free to ask if you have further questions.

hmassalha commented 3 months ago

Exactly the opposite. I want the zero value to be matching to white color but the two sides of the colorbar should be a symmetric since we have two different dynamic ranges from both ends. in this case, the blue side of the color bar should be shorter reaching dark blue at -1.6 The red side of the colorbar should be longer since we have more distance from 0 to 4. Thanks.

Mr-Milk commented 3 months ago

Then you are doing the right thing before with TwoSlopeNorm. The colorbar will always have uniform color range but scaled value. What you want is uniform values with scaled color range, I'm afraid this is very difficult to achieve at the moment.

hmassalha commented 3 months ago

Ok thanks. Would it possibly to control the colobar tick’s appearance so it will have more information about the dynamic range of each side of the colorbar, otherwise it is difficult to like the values to the heatmap. Thanks.

Mr-Milk commented 3 months ago

I'm afraid not, an alternative way is to use the custom_legend to add your own legend to the plot, it will have to be an matplotlib Artist object.

Mr-Milk commented 3 months ago

If you want control like how many ticks to display and the format, there is a parameter cbar_kws for Heatmap, it will pass to legendkit's colorart.