holoviz / hvplot

A high-level plotting API for pandas, dask, xarray, and networkx built on HoloViews
https://hvplot.holoviz.org
BSD 3-Clause "New" or "Revised" License
1.08k stars 105 forks source link

xarray DataSet support for `hvplot.explorer()` #915

Closed itsgifnotjiff closed 7 months ago

itsgifnotjiff commented 2 years ago

Thank you so much for your wonderful work and here is a feature request to implement the hvplot.explorer() function to support Xarray DataSets of Gridded data so we can explore the different dims and data_vars as we can for normal tabular DataFrames. I believe it is pretty clear but I am happy to elaborate further if need be. Below is an app I created where the Panel.Widgets are created and instanciated dynamically so that on file select you have the approriate Widgets for that particular file. I would love to have this be done in an officially supported way as I am a new programmer and I am sure there is a better way.

image

jbednar commented 2 years ago

Pretty! The Explorer did support Xarray at some point, but there were issues when we were preparing the release and we decided to disable it so as not to delay the release further. Definitely good to revisit that now!

itsgifnotjiff commented 2 years ago

Thank you Mr. @jbednar . I used a simple set of functions to dynamically create the widgets and populate them with the available values. I am a new programer so I do not think my code is any good but is it at least hinting at a library wide solution for xarrays sir?

def open_dataset(file) -> xr.Dataset:
    key = f"file {file}"
    if not key in pn.state.cache:
        pn.state.cache[key]=xr.open_dataset(file)
    return pn.state.cache[key]

def get_sub_dataset(file, field):
    xds = open_dataset(file)
    return xds[field]

def get_options(file, field):
    options = {}
    xds_sub = get_sub_dataset(file, field)
    for (_, d) in enumerate(xds_sub.dims):
        for (_, c) in enumerate(xds_sub.coords):
            if d == c and (d != "lon" and d != "lat"):
                if xds_sub.coords[c].dtype == np.dtype("<M8[ns]"):
                    time_list = []
                    for _, el in np.ndenumerate(
                        xds_sub.coords["time"].values
                    ):
                        time_list.append(np.datetime_as_string(el, timezone="UTC"))
                    options[d] = time_list
                else:
                    options[d] = xds_sub.coords[c].values.tolist()
    return options

def plot(xds_sub,colormap, **kwargs):
    return (xds_sub
        .sel(**kwargs)
        .hvplot(
            kind="quadmesh",
            rasterize=True,
            data_aspect=1,
            frame_height=500,
            cmap=colormap,
            crs=ccrs.PlateCarree(),
            projection=ccrs.PlateCarree(),
            project=True,
            geo=True,
            coastline=True,
            global_extent=True,
        )
    )

# App Components

def main_component():
    xds = open_dataset(file_list[0])

    select_file = pnw.Select(name="File", options=file_list).servable(target="sidebar")
    select_field = pnw.Select(name="Field", value="HU", options=list(xds.data_vars)).servable(target="sidebar")
    cmap_sel = pnw.Select(name="Colormap", value="jet",options=['cool','hot','jet','viridis','brg','rainbow'])
    return [
        select_file,select_field,cmap_sel,
        pn.bind(sub_component, file=select_file, field=select_field, colormap=cmap_sel)
    ]

def sub_component(file, field,colormap):
    xds_sub = get_sub_dataset(file=file, field=field)
    widgets = get_widgets(file=file, field=field)

    return pn.Column(
        pn.Row(*widgets.values()),
        pn.panel(pn.bind(plot, xds_sub,colormap, **widgets)),
    )

def get_widgets(file, field):
    options=get_options(file, field)
    # print("Options for Debugging : ",file,field,options)
    return {key: pnw.DiscreteSlider(options=value, name=key) for key, value in options.items()}
ahuang11 commented 7 months ago

Initial support for xarray is now implemented https://hvplot.holoviz.org/user_guide/Explorer.html#supported-data-inputs

There are still some issues with it, namely variable selection, but that's logged https://github.com/holoviz/hvplot/issues/1273