2

I am trying to generate 2D line plots at different angles or slices of a matplotlib contourf plot.

As an example from the matplotlib contourf demo example below

import numpy as np
import matplotlib.pyplot as plt

origin = 'lower'

delta = 0.025

x = y = np.arange(-3.0, 3.01, delta)
X, Y = np.meshgrid(x, y)
Z1 = np.exp(-X**2 - Y**2)
Z2 = np.exp(-(X - 1)**2 - (Y - 1)**2)
Z = (Z1 - Z2) * 2

nr, nc = Z.shape


fig1, ax2 = plt.subplots(constrained_layout=True)
CS = ax2.contourf(X, Y, Z, 10, cmap=plt.cm.viridis, origin=origin,extend='both')



ax2.set_title('Random Plot')
ax2.set_xlabel('X Axis')
ax2.set_ylabel('Y Axis')
cbar = fig1.colorbar(CS)

Ideally, I want to generate lines at different angles (30,45,60 degrees) across the map (starting at any arbitrary point till the end of existing array) and then plot the Z variations across that line.

I think a simpler problem in principle would be, lines from (X2,Y2) to (X1,Y1) and plot the Z variation for the given contour (which is already interpolated data).

As an example, original problem would be line from (-3,-3) at angle 45 deg across. Analogous problem would be lets say a line from (-3,-3) to (3,3) and plot the Z variation at different locations on that line.

The source contour plot generated is : Contourf Plot

ssj
  • 35
  • 7

1 Answers1

1

Here is a rather inefficient approach, but it does the job. It recalculates the function on a new grid of which it only needs the diagonal.

import numpy as np
import matplotlib.pyplot as plt
from scipy.interpolate import RectBivariateSpline

delta = 0.025

x = y = np.arange(-3.0, 3.01, delta)
X, Y = np.meshgrid(x, y)
Z1 = np.exp(-X ** 2 - Y ** 2)
Z2 = np.exp(-(X - 1) ** 2 - (Y - 1) ** 2)
Z = (Z1 - Z2) * 2

nr, nc = Z.shape

x1, y1 = -3, -2
x2, y2 = 3, 2

fig, (ax1, ax2) = plt.subplots(ncols=2, figsize=(15, 5))
CS = ax1.contourf(X, Y, Z, 10, cmap=plt.cm.viridis, origin='lower', extend='both')
ax1.plot([x1, x2], [y1, y2], color='k', ls='--', lw=3, alpha=0.6)
ax1.set_xlabel('X Axis')
ax1.set_ylabel('Y Axis')
cbar = fig.colorbar(CS, ax=ax1)

spline_func = RectBivariateSpline(x, y, Z)
xline = np.linspace(x1, x2, 200)
yline = np.linspace(y1, y2, 200)
zline = spline_func(xline, yline)
ax2.plot(xline, zline.diagonal())
ax2.set_xlabel('X Axis')
ax2.set_ylabel('Z Axis')

plt.show()

example plot

Mr. T
  • 11,960
  • 10
  • 32
  • 54
JohanC
  • 71,591
  • 8
  • 33
  • 66
  • Thanks, I think it works for this example, but since this was an MVE, I generated the Z function as an example. What if i don't know the actual Z function and the Z values are sparse measured data with interpolated values in between. Any way we can match the values of Z at xline,yline locations without knowing the actual function? I wasn't sure how to extract the zline values without calculating based on the original (only matching). – ssj Mar 03 '21 at 19:48
  • 1
    The code for the curve only uses the points with which the contour plot is created; it doesn't use the function with which Z was calculated. If your Z-values aren't located on a grid, you can calculate an interpolated grid via [`scipy.interpolate.griddata`](https://docs.scipy.org/doc/scipy/reference/generated/scipy.interpolate.griddata.html). – JohanC Mar 03 '21 at 20:28
  • 1
    I see it now, thanks. I think i found another solution which isn't exactly what I need but a good starting point - alongside JohanC's solution. https://stackoverflow.com/questions/7878398/how-to-extract-an-arbitrary-line-of-values-from-a-numpy-array – ssj Mar 04 '21 at 01:08
  • I got this to work using cartesian coordinates. I was wondering if anyone has an idea on how to draw lines in polar coordinates instead of cartesian, and then converting it to cartesian to get specific angles? How would we specify the radius (since it needs to be bounded in the current space ? – ssj Mar 05 '21 at 04:31