Plot wind vectors from a XArray DataArray


I am trying to plot temperature and wind data from a Xarray data array.

To show what I want to achieve, I have attached an example Matplotlib plot and a GMT plot that somewhat mimics it, here still without the wind vectors. The plot is made with GMT 6.1.1 and pygmt 0.2.0.

I am getting stuck trying to plot the wind vectors.

How should I proceed in pygmt? I tried:

fig.plot(lons.values, lats.values, direction=[u.values, v.values], style='V')

which yields:

    GMTInvalidInput                           Traceback (most recent call last)
    <ipython-input-174-4dd1ef6c1a08> in <module>
         36 fig.coast(projection=PROJECTION, region=REGION, frame="g", land="gray")
         37 fig.grdimage(windspeed.isel(isobaricInhPa=0), n='b', Q=True)
    ---> 38 fig.plot(lons.values, lats.values, direction=[u.values, v.values], style='V')
         39 fig.coast(projection=PROJECTION, region=REGION, frame="g", shorelines=True)
         40 fig.text(position='BL',text='d.', font=label_font)

    ~/opt/miniconda3/envs/pygmt/lib/python3.6/site-packages/pygmt/helpers/ in new_module(*args, **kwargs)
        235                 if alias in kwargs:
        236                     kwargs[arg] = kwargs.pop(alias)
    --> 237             return module_func(*args, **kwargs)
        239         new_module.aliases = aliases

    ~/opt/miniconda3/envs/pygmt/lib/python3.6/site-packages/pygmt/helpers/ in new_module(*args, **kwargs)
        372                         kwargs[arg] = separators[fmt].join(f"{item}" for item in value)
        373             # Execute the original function and return its output
    --> 374             return module_func(*args, **kwargs)
        376         return new_module

    ~/opt/miniconda3/envs/pygmt/lib/python3.6/site-packages/pygmt/ in plot(self, x, y, data, sizes, direction, **kwargs)
        561                 )
    --> 563             with file_context as fname:
        564                 arg_str = " ".join([fname, build_arg_string(kwargs)])
        565                 lib.call_module("plot", arg_str)

    ~/opt/miniconda3/envs/pygmt/lib/python3.6/ in __enter__(self)
         79     def __enter__(self):
         80         try:
    ---> 81             return next(self.gen)
         82         except StopIteration:
         83             raise RuntimeError("generator didn't yield") from None

    ~/opt/miniconda3/envs/pygmt/lib/python3.6/site-packages/pygmt/clib/ in virtualfile_from_vectors(self, *vectors)
       1160         rows = len(arrays[0])
       1161         if not all(len(i) == rows for i in arrays):
    -> 1162             raise GMTInvalidInput("All arrays must have same size.")
       1164         family = "GMT_IS_DATASET|GMT_VIA_VECTOR"

    GMTInvalidInput: All arrays must have same size.

Any help would be greatly appreciated!

p.s. the fig.plot() is part of a larger pygmt call, for context:

label_font = '14p,Helvetica-Bold,black'
REGION = 'g'
PROJECTION = 'G-35/60/8c'
# Figuur D
fig.coast(projection=PROJECTION, region=REGION, frame="g", land="gray")
fig.grdimage(windspeed.isel(isobaricInhPa=0), n='b', Q=True)
fig.plot(lons.values, lats.values, direction=[u.values, v.values], style='V')
fig.coast(projection=PROJECTION, region=REGION, frame="g", shorelines=True)
fig.text(position='BL',text='d.', font=label_font)

Hi @jdassink, welcome to the GMT forum!

I’m not too familiar with plotting velocity vectors, but the GMTInvalidInput error message you’re getting indicates that your arrays (lons, lats, u and v) are probably of different lengths. Perhaps do a print(len(lons.values), len(lats.values), len(u.values), len(v.values)) and see if they are the same.

If not, maybe upload a sample of your xarray.DataArray (e.g. as a zipped NetCDF file) so that we can take a look at what’s wrong?

As an aside, if you want to get the pointy colorbar like in the matplotlib plot, do fig.colorbar(position="JBC+e") (key is the +e which adds sidebar triangles). See also

P.S. There’s a PR in progress for velo at which may be of interest if you need to plot more complicated velocity vectors (e.g. with error ellipses and annotations).

Hi @weiji14, thanks for your answer.

I tried a bit more and decided to use grdvector by using the GMT clib directly.
I advanced a bit in my figure, and now am almost able to produce what I want. Basically the call that is use is:

fig.coast(projection=PROJECTION, region=REGION, frame="g", land="gray")
fig.grdimage(windspeed.isel(isobaricInhPa=0), n='b', Q=True)
fig.coast(projection=PROJECTION, region=REGION, frame="g", shorelines=True)
with pygmt.clib.Session() as session:
                        f'u.grd v.grd -I10d/10d -Gwhite -Q0.1i+e+gwhite -W0.8p,black -Si0.1d')
fig.text(position='BL',text='d.', font=label_font)

and so forth for the other subfigures.

I get the following plot:

It shows these weird effects around the poles. Any idea?


I have been having the same error message (GMTInvalidInput: All arrays must have same size). I checked the length of each array and they are equal:


Here is what I try to do:

fig = pygmt.Figure()
fig.basemap(region=region, projection=proj, frame=True)
fig.grdimage("ETOPO1_Ice_g_geotiff.tif", projection=proj, frame=True, cmap="oleron")
fig.colorbar(frame='af+l"Topography (m)"')

Many thanks!

Despite my PyIgnorance I strongly suspect of the above line

Hi Joaquim! Would you have any suggestion how I should code this instead?


Sure, remove that trouble-maker " : " from file.

EDIT: hoops, we are mixing the threads.

Hmm, looking at, I’m guessing that you should do direction=[azi, mag] instead? What type of Python objects are azi and mag?

Fixed it! I needed to plot it as direction=[azi, mag] indeed. Also, my angles were in radians, not degrees, so that’s why I kept running into the problem of only north-facing vectors when it did work :sweat_smile:

1 Like