-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support grid of heatmaps #208
Comments
The multiple subplots mechanics comes from the xarray plotting library (https://docs.xarray.dev/en/latest/user-guide/plotting.html#faceting). Your solution with It would be cool (and consistent) to be able to declare a subplot in the same way for |
Yes, it would indeed be nice if all our seaborn based functions could also be used for subplots. I looked a bit into seaborn facetgrid at first since I was confused between their facetgrid and xarray facetgrids. So we could either continue with seaborn and transform xarray.Da components into dataframes or switch to .imshow() |
I personnaly like seaborn heatmap more. It has useful features like |
I tried playing with |
generate figure below with new figanos import matplotlib.pyplot as plt
import xarray as xr
import numpy as np
import figanos.matplotlib as fg
# create xarray object from a NetCDF
url = 'https://pavics.ouranos.ca//twitcher/ows/proxy/thredds/dodsC/birdhouse/disk2/cccs_portal/indices/Final/BCCAQv2_CMIP6/tx_max/YS/ssp585/ensemble_percentiles/tx_max_ann_BCCAQ2v2+ANUSPLIN300_historical+ssp585_1950-2100_30ymean_percentiles.nc'
opened = xr.open_dataset(url, decode_timedelta=False)
ds_space = opened[['tx_max_p50']].isel(time=[0, 1, 2]).sel(lat=slice(40,65), lon=slice(-90,-55))
# subset and select variable
sl = slice(100,100+5)
da = ds_space.isel(lat=sl, lon=sl).drop("horizon").tx_max_p50
da = da.rename({"lat":"model", "lon":"prop"})
da = da.assign_coords(model=[f"s{n}" for n in np.arange(da.model.size)], prop=[f"p{m}" for m in np.arange(da.prop.size)])
fg.heatmap(da, plot_kw = {"col": "time", "annot":True}, fig_kw={"figsize":(14,4)}) I'm getting this with a relatively simple modification of the heart of the change in figanos # plot
if ax is not None:
sns.heatmap(df, ax=ax, **plot_kw)
# format
plt.xticks(rotation=45, ha="right", rotation_mode="anchor")
ax.tick_params(axis="both", direction="out")
set_plot_attrs(
use_attrs,
da,
ax,
title_loc="center",
wrap_kw={"min_line_len": 35, "max_line_len": 44},
)
return ax
else:
def draw_heatmap(*args, **kwargs):
data = kwargs.pop('data')
d = data.pivot(index=args[1], columns=args[0], values=args[2])
sns.heatmap(d, **kwargs)
plt.figure(**fig_kw)
g = sns.FacetGrid(df, col=plot_kw["col"], row=plot_kw["row"])
plot_kw.pop("col")
plot_kw.pop("row")
cax = g.fig.add_axes([.92, .12, .02, .8])
ax = g.map_dataframe(draw_heatmap, *heatmap_dims, da_name, **plot_kw, cbar=True, cbar_ax=cax)
g.fig.subplots_adjust(right=.9)
if "figsize" in fig_kw.keys():
g.fig.set_size_inches(*fig_kw["figsize"])
plt.xticks(rotation=45, ha="right", rotation_mode="anchor")
return g |
nice ! Does this mean that heatmap will return a FacetGrid even if it is 1 subplot ? I suggest changing the I think it's okay that we have to play with |
If you specify some out = fg.heatmap(da.isel(time=0), plot_kw={"col":"time"})
print(type(out))
>>> <class 'seaborn.axisgrid.FacetGrid'>
out = fg.heatmap(da.isel(time=0))
print(type(out))
>>><class 'matplotlib.axes._axes.Axes'> It's similar to
Ok, got it, I changed this in my PR (#219 ). There was already a check before, this condition is |
Addressing a Problem?
I was trying to use
fg.heatmap
in the same way asfg.gridmap
, supplyingplot_kw = dict(col="time")
, but it seems in this case we need a two-dimensional dataset, already prepared for asns.heatmap
.I took the example
ds_space
from the tutorial, but I take a small square subset of a map, and identify lat -> model, lon -> prop, just to imitate a heatmap with this part of the tutorial:If I select a single time point, everything is good for a heatmap,
fg.heatmap(da.isel(time=0).drop("time"))
But I can't naively ask for
fg.heatmap(da, plot_kw={"col":"time"})
as mentioned above, I getHoping
fg.gridmap
may handle my use case, I try:fg.gridmap(da, plot_kw={"col":"time"})
, but the strings I put in my coordinates are posing a problem:so this is not intended for this use. I can still replace my coordinates
fg.gridmap(da.assign_coords(model=np.arange(da.model.size), prop=np.arange(da.prop.size)), plot_kw={"col":"time"})
, I get:the coordinates are dropped altogether
Potential Solution
I'm not sure if this use case is intended to be use gridmap for this purpose? Currently I'm just using
plt.imshow
directlyda.plot.imshow(col="time")
, which works well enough for me :Additional context
Have other people used grids of heatmaps with figanos? Is there something obvious I'm not seeing?
Contribution
The text was updated successfully, but these errors were encountered: