sdegelia
sdegelia

Reputation: 33

Contouring non-uniform 2d data in python/matplotlib above terrain

I am having trouble contouring some data in matplotlib. I am trying to plot a vertical cross-section of temperature that I sliced from a 3d field of temperature.

My temperature array (T) is of size 50*300 where 300 is the number of horizontal levels which are evenly spaced. However, 50 is the number of vertical levels that are: a) non-uniformly spaced; and b) have a different starting level for each vertical column. As in there are always 50 vertical levels, but sometimes they span from 100 - 15000 m, and sometimes from 300 - 20000 m (due to terrain differences).

I also have a 2d array of height (Z; same shape as T), a 1d array of horizontal location (LAT), and a 1d array of terrain height (TER).

I am trying to get a similar plot to one like here in which you can see the terrain blacked out and the data is contoured around it.

My first attempt to plot this was to create a meshgrid of horizontal distance and height, and then contourf temperature with those arguments as well. However numpy.meshgrid requires 1d inputs, and my height is a 2d variable. Doing something like this only begins contouring upwards from the first column:

ax1 = plt.gca()
z1, x1 = np.meshgrid(LAT, Z[:,0])
plt.contourf(z1, x1, T)
ax1.fill_between(z1[0,:], 0, TER, facecolor='black')

Which produces this. If I use Z[:,-1] in the meshgrid, it contours underground for columns to the left, which obviously I don't want. What I really would like is to use some 2d array for Z in the meshgrid but I'm not sure how to go about that.

I've also looked into the griddata function but that requires 1D inputs as well. Anyone have any ideas on how to approach this? Any help is appreciated!

Upvotes: 2

Views: 2065

Answers (1)

nicoguaro
nicoguaro

Reputation: 3871

For what I understand your data is structured. Then you can directly use the contourf or contour option in matplotlib. The code you present have the right idea but you should use

x1, z1 = np.meshgrid(LAT, Z[:,0])
plt.contourf(x1, Z, T)

for the contours. I have an example below

import numpy as np
import matplotlib.pyplot as plt


L, H = np.pi*np.mgrid[-1:1:100j, -1:1:100j]
T = np.cos(L)*np.cos(2*H)
H = np.cos(L) + H

plt.contourf(L, H, T, cmap="hot")
plt.show()

Look that the grid is generated with the original bounding box, but the plot is made with the height that has been transformed and not the initial one. Also, you can use tricontour for nonstructured data (or in general), but then you will need to generate the triangulation (that in your case is straightforward).

enter image description here

Upvotes: 1

Related Questions