Highres quiver plot returning memory error

Anyway, I tried to do the following and it didn’t affect the plot:

def filter_points(vectorfield, x_range, y_range):
    if x_range is None or y_range is None:
        return vectorfield
    
    return vectorfield[x_range, y_range].iloc[::10].iloc[::10]

Oops, I think you have the right idea; I think you need something like:

import numpy as np
import xarray as xr
import hvplot.xarray  # noqa
import holoviews as hv
import panel as pn


# def sample_data(shape=(904, 999)):
def sample_data(shape=(90, 90)):
    x = np.linspace(311.9, 391.1, shape[1])
    y = np.linspace(-23.6, 24.8, shape[0])

    x2d, y2d = np.meshgrid(x, y)
    u = 10 * (2 * np.cos(2 * np.deg2rad(x2d) + 3 * np.deg2rad(y2d + 30)) ** 2)
    v = 20 * np.cos(6 * np.deg2rad(x2d))

    return x, y, u, v


xs, ys, U, V = sample_data()

mag = np.sqrt(U**2 + V**2)
angle = (np.pi / 2.0) - np.arctan2(U / mag, V / mag)

ds = xr.Dataset(
    {
        "mag": xr.DataArray(mag, dims=("y", "x"), coords={"y": ys, "x": xs}),
        "angle": xr.DataArray(angle, dims=("y", "x"), coords={"y": ys, "x": xs}),
    }
)


def create_quiver(x_range, y_range, nmax=10):
    quiver = ds.hvplot.vectorfield(
        x="x",
        y="y",
        mag="mag",
        angle="angle",
        hover=False,
    ).opts(magnitude="mag")
    if x_range is None or y_range is None:
        return quiver
    # dump logic here
    return quiver


range_xy = hv.streams.RangeXY()
filtered = hv.DynamicMap(create_quiver, streams=[range_xy])
range_xy.source = filtered
filtered

So this should work, but doesn’t…

import numpy as np
import xarray as xr
import hvplot.xarray  # noqa
import holoviews as hv
import panel as pn


# def sample_data(shape=(904, 999)):
def sample_data(shape=(90, 90)):
    x = np.linspace(311.9, 391.1, shape[1])
    y = np.linspace(-23.6, 24.8, shape[0])

    x2d, y2d = np.meshgrid(x, y)
    u = 10 * (2 * np.cos(2 * np.deg2rad(x2d) + 3 * np.deg2rad(y2d + 30)) ** 2)
    v = 20 * np.cos(6 * np.deg2rad(x2d))

    return x, y, u, v


xs, ys, U, V = sample_data()

mag = np.sqrt(U**2 + V**2)
angle = (np.pi / 2.0) - np.arctan2(U / mag, V / mag)

ds = xr.Dataset(
    {
        "mag": xr.DataArray(mag, dims=("y", "x"), coords={"y": ys, "x": xs}),
        "angle": xr.DataArray(angle, dims=("y", "x"), coords={"y": ys, "x": xs}),
    }
)




def create_quiver(x_range, y_range, nmax = 10):
    quiver = ds.hvplot.vectorfield(
        x="x",
        y="y",
        mag="mag",
        angle="angle",
        hover=False,
    ).opts(magnitude="mag")
    
    if x_range is None or y_range is None:
        return quiver

    sub = ds.sel(x = slice(*x_range), y = slice(*y_range))

    xs, ys = sub.x.size, sub.y.size
    ix, iy = xs // nmax, ys // nmax
    
    ix = 1 if ix <= 0 else ix
    iy = 1 if iy <= 0 else iy
    
    return quiver.select(x = x_range, y = y_range).iloc[::ix].iloc[::iy]


range_xy = hv.streams.RangeXY()
filtered = hv.DynamicMap(create_quiver, streams=[range_xy])
range_xy.source = filtered
filtered

I feel I am doing something dumb here… I even got excited with the example you gave me and tried a little bit further, but also dont work.

def create_quiver(x_range, y_range, nmax = 10):
    if x_range is None or y_range is None:
        quiver = ds.hvplot.vectorfield(
            x="x",
            y="y",
            mag="mag",
            angle="angle",
            hover=False,
        ).opts(magnitude="mag")
        return quiver

    sub = ds.sel(x = slice(*x_range), y = slice(*y_range))

    xs, ys = sub.x.size, sub.y.size
    ix, iy = xs // nmax, ys // nmax

    ix = 1 if ix <= 0 else ix
    iy = 1 if iy <= 0 else iy

    sub = sub.coarsen(x = ix, y = iy, side = "center", boundary = "trim").mean()
    
    quiver = sub.hvplot.vectorfield(
        x="x",
        y="y",
        mag="mag",
        angle="angle",
        hover=False,
    ).opts(magnitude="mag")
    
    return quiver

Again, thanks for all help…

Can you clarify what’s not working?

Your first example seems to work fine at a glance:

import numpy as np
import xarray as xr
import hvplot.xarray  # noqa
import holoviews as hv
import panel as pn


# def sample_data(shape=(904, 999)):
def sample_data(shape=(90, 90)):
    x = np.linspace(311.9, 391.1, shape[1])
    y = np.linspace(-23.6, 24.8, shape[0])

    x2d, y2d = np.meshgrid(x, y)
    u = 10 * (2 * np.cos(2 * np.deg2rad(x2d) + 3 * np.deg2rad(y2d + 30)) ** 2)
    v = 20 * np.cos(6 * np.deg2rad(x2d))

    return x, y, u, v


xs, ys, U, V = sample_data()

mag = np.sqrt(U**2 + V**2)
angle = (np.pi / 2.0) - np.arctan2(U / mag, V / mag)

ds = xr.Dataset(
    {
        "mag": xr.DataArray(mag, dims=("y", "x"), coords={"y": ys, "x": xs}),
        "angle": xr.DataArray(angle, dims=("y", "x"), coords={"y": ys, "x": xs}),
    }
)




def create_quiver(x_range, y_range, nmax = 10):
    quiver = ds.hvplot.vectorfield(
        x="x",
        y="y",
        mag="mag",
        angle="angle",
        hover=False,
    ).opts(magnitude="mag")
    
    if x_range is None or y_range is None:
        return quiver

    sub = ds.sel(x = slice(*x_range), y = slice(*y_range))

    xs, ys = sub.x.size, sub.y.size
    ix, iy = xs // nmax, ys // nmax
    
    ix = 1 if ix <= 0 else ix
    iy = 1 if iy <= 0 else iy
    print(ix, iy, x_range, y_range)
    return quiver.select(x = x_range, y = y_range).iloc[::ix].iloc[::iy]


range_xy = hv.streams.RangeXY()
filtered = hv.DynamicMap(create_quiver, streams=[range_xy])
range_xy.source = filtered
filtered

This also works:

import numpy as np
import xarray as xr
import hvplot.xarray  # noqa
import holoviews as hv
import panel as pn


# def sample_data(shape=(904, 999)):
def sample_data(shape=(90, 90)):
    x = np.linspace(311.9, 391.1, shape[1])
    y = np.linspace(-23.6, 24.8, shape[0])

    x2d, y2d = np.meshgrid(x, y)
    u = 10 * (2 * np.cos(2 * np.deg2rad(x2d) + 3 * np.deg2rad(y2d + 30)) ** 2)
    v = 20 * np.cos(6 * np.deg2rad(x2d))

    return x, y, u, v


xs, ys, U, V = sample_data()

mag = np.sqrt(U**2 + V**2)
angle = (np.pi / 2.0) - np.arctan2(U / mag, V / mag)

ds = xr.Dataset(
    {
        "mag": xr.DataArray(mag, dims=("y", "x"), coords={"y": ys, "x": xs}),
        "angle": xr.DataArray(angle, dims=("y", "x"), coords={"y": ys, "x": xs}),
    }
)


def subset_quiver(quiver, x_range, y_range, nmax=10):
    if x_range is None or y_range is None:
        return quiver

    sub = ds.sel(x=slice(*x_range), y=slice(*y_range))

    xs, ys = sub.x.size, sub.y.size
    ix, iy = xs // nmax, ys // nmax

    ix = 1 if ix <= 0 else ix
    iy = 1 if iy <= 0 else iy
    return quiver[x_range, y_range].iloc[::ix].iloc[::iy]


quiver = ds.hvplot.vectorfield(
    x="x",
    y="y",
    mag="mag",
    angle="angle",
    hover=False,
    width=300,
).opts(magnitude="mag")
range_xy = hv.streams.RangeXY(source=quiver)
filtered = quiver.apply(subset_quiver, streams=[range_xy]).clone()
filtered.opts(title="filtered") + quiver.opts(title="original")

I am sorry, I thought that as I was not using panel controls it would be fine using JupyterLab Editor Console, but it turns out things in general doesn’t work well on it, as discussed here.

I ran the following code and it works fine and I consider this the solution of the original problem.
Thank you very much @ahuang11 and @jbednar . I plan to create an example to add to the gallery. Any suggestion on where to put it?

Code that works very sharp even though with 2000 x 2000 = 4,000,000 points:
To make it clear, the code works because it coarsen the data box averaging the data to keep always 10 x 10 = 100 arrows in the view. Of course, if there is nothing to average, it will just show all arrows. This is a very nice combination of xarray and hvplot.

import numpy as np
import xarray as xr
import hvplot.xarray  # noqa
import holoviews as hv
import panel as pn


def sample_data(shape=(2000, 2000)):
    x = np.linspace(311.9, 391.1, shape[1])
    y = np.linspace(-23.6, 24.8, shape[0])

    x2d, y2d = np.meshgrid(x, y)
    u = 10 * (2 * np.cos(2 * np.deg2rad(x2d) + 3 * np.deg2rad(y2d + 30)) ** 2)
    v = 20 * np.cos(6 * np.deg2rad(x2d))

    return x, y, u, v


xs, ys, U, V = sample_data()

mag = np.sqrt(U**2 + V**2)
angle = (np.pi / 2.0) - np.arctan2(U / mag, V / mag)

ds = xr.Dataset(
    {
        "mag": xr.DataArray(mag, dims=("y", "x"), coords={"y": ys, "x": xs}),
        "angle": xr.DataArray(angle, dims=("y", "x"), coords={"y": ys, "x": xs}),
    }
)


def create_quiver(x_range, y_range, nmax = 10):
    if x_range is None or y_range is None:
        xs, ys = ds.x.size, ds.y.size
        ix, iy = xs // nmax, ys // nmax
    
        ix = 1 if ix <= 0 else ix
        iy = 1 if iy <= 0 else iy
    
        sub = ds.coarsen(x = ix, y = iy, side = "center", boundary = "trim").mean()
        quiver = sub.hvplot.vectorfield(
            x="x",
            y="y",
            mag="mag",
            angle="angle",
            hover=False,
        ).opts(magnitude="mag")
        return quiver

    sub = ds.sel(x = slice(*x_range), y = slice(*y_range))

    xs, ys = sub.x.size, sub.y.size
    ix, iy = xs // nmax, ys // nmax

    ix = 1 if ix <= 0 else ix
    iy = 1 if iy <= 0 else iy

    sub = sub.coarsen(x = ix, y = iy, side = "center", boundary = "trim").mean()
    
    quiver = sub.hvplot.vectorfield(
        x="x",
        y="y",
        mag="mag",
        angle="angle",
        hover=False,
    ).opts(magnitude="mag")
    
    return quiver


range_xy = hv.streams.RangeXY()
filtered = hv.DynamicMap(create_quiver, streams=[range_xy])
range_xy.source = filtered
filtered

Generates this very cool result!

ezgif.com-video-to-gif (4)

2 Likes

The immediate place is the Discourse Showcase here. Other than that, perhaps here too?
https://holoviews.org/gallery/index.html

Also, if you use social media, we’d love to repost it!

1 Like