0

I have an xarray Dataset called dens that I would like to plot.

This is the Dataset:

<xarray.Dataset>
Dimensions:  (time: 641, lat: 30, lon: 30)
Coordinates:
  * time     (time) datetime64[ns] 2013-07-01T12:00:00 ... 2013-08-02T12:00:00
  * lon      (lon) float64 32.73 32.83 32.94 33.05 ... 35.53 35.64 35.75 35.85
  * lat      (lat) float64 31.08 31.27 31.47 31.66 ... 36.06 36.25 36.44 36.63
Data variables:
    density  (time, lat, lon) float64 2e+03 0.0 0.0 0.0 0.0 ... 0.0 0.0 0.0 0.0

I am using the command


plt.contourf(dens.density.values[-1,:,:]);

to plot it and it's working, but since I would like to have the coastline also drawn on the plot, I am also trying to use

m = Basemap(llcrnrlon=data['lon'].min(), llcrnrlat=data['lat'].min(),
                urcrnrlon=data['lon'].max(), urcrnrlat=data['lat'].max(), resolution='i', suppress_ticks=1)
m.drawcoastlines();
m.fillcontinents(color='gray',lake_color='gray');

But when I run all of the commands, and then run plt.show() ,the contour plot disappears, and all that it shows me is the coastline.

How could I fix this to get a contour plot + the coastline plot in the same figure?

Sorry if this is a silly question, but i'm pretty new to python

Thank you for any help,

Yotam

EDIT: I only just now realized that I am trying to combine two different "toolkits", and that there is a possibility to do all of this using only the basemap toolkit, but just trying to write

m.contourf(dens.density.values[-1,:,:]);

gives me this error:

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
Cell In[21], line 1
----> 1 m.contourf(dens.density.values[-1,:,:])

TypeError: Basemap.contourf() missing 2 required positional arguments: 'y' and 'data'

ANOTHER EDIT: I keep discovering more things as I go along, after reading the documentation of Basemap, I realized that the syntax of the command should be something like this

m.contourf(dens.lon.values,dens.lat.values,dens.density.values[-1,:,:]);

but now I get this error:

IndexError: too many indices for array: array is 1-dimensional, but 2 were indexed

I'm guessing this is because of my density array, which is 2D, but how do I extract from it just the density values? I'm using the [-1] in the time dimension because I only actually need the last timestep

Again, thanks in advance, Yotam

LAST EDIT

This is the final plot, how can I make the land around to be grey instead of purple? Also, is there a way to depict a larger geographical area, just a bit larger, without messing with the data?

enter image description here

This is the new figure with my actual data

enter image description here

3
  • Is it possible to share the dataset that you are using? Then I could try it too.
    – molinav
    Commented Jan 27, 2024 at 15:06
  • Can you add somepart of the data so I can use it to try a solution?
    – Cem Koçak
    Commented Jan 27, 2024 at 17:49
  • @molinav I figured out thanks to the answer below, but now I have a new question, how would I be able to change the colorbar? For example to be able to control the values of where the colors change? Commented Jan 31, 2024 at 15:33

1 Answer 1

1

plotting with basemap and xarray is already discussed here.

m = Basemap(llcrnrlon=data['lon'].min(), llcrnrlat=data['lat'].min(),
            urcrnrlon=data['lon'].max(), urcrnrlat=data['lat'].max(), 
  resolution='i', suppress_ticks=1)
m.drawcoastlines();
m.fillcontinents(color='gray',lake_color='gray')
dens.density[-1,:,:].plot.contourf()
plt.show()

The above code should work. I use cartopy for features like coastlines and borders. Below is the working code snippet for you to try with your dataset.

import xarray as xr
import matplotlib.pyplot as plt
import cartopy.crs as ccrs
import cartopy.feature as cf

ds = xr.open_dataset('filename.nc')
fig = plt.figure(figsize=(8,8))
crs=ccrs.PlateCarree()
ax = fig.add_subplot(1,1,1, projection=crs)
gl = ax.gridlines(crs=crs, draw_labels=True,
                linewidth=0.01, color='gray', alpha=0.5, linestyle='-.')

ax.add_feature(cf.COASTLINE.with_scale("50m"), lw=0.5)
ax.add_feature(cf.BORDERS.with_scale("50m"), lw=0.3)

ds.density[-1,:,:].plot.contourf()
plt.show()

For the last edit

To set all the purple(zeros) to white you can use the following cmap.

from matplotlib.colors import LinearSegmentedColormap
cm = LinearSegmentedColormap.from_list('', ['white', *plt.cm.Blues(np.arange(255))])
ds.density[-1,:,:].plot.contourf(cmap=cm)
8
  • Thank you so very much! I just tried running the first lines of code and it worked! I will also try using the code you wrote using cartopy, to see if it also works. Commented Jan 28, 2024 at 19:16
  • I also tried your cartopy code, it also works really well, even looks better than the basemap figure. Just a couple of questions that apply to both approaches.The figure returns the land as purple, since purple is the colour that depicts values of 0 on my density scale, could this be changed to be grey? Also, is there any way of expanding the geographical area that is portrayed? I will try to find a way to post the figure here so you can see what it looks like. Thank you again for your help and patience Commented Jan 30, 2024 at 14:07
  • I will edit the original question and post the plot there Commented Jan 30, 2024 at 14:12
  • I have one more final question, and this one is relevant whether I use either the Basemap or the cartopy code. How can I change the default colorbar? I would like to split it into more color divisions? Commented Jan 31, 2024 at 15:30
  • 1
    You can use vmax, vmin keywords to limit the values in the contourf function.
    – strawhat
    Commented Jan 31, 2024 at 16:53

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.