how can I plot missing points to a full circle?

Viewed 163

I have 9 temperature points. 1 in the center and 8 on the circle. I need to create a heatmap in a circle. I set the points at which to perform calculations, and use the scipy.interpolate.griddata, but the full circle is not drawn, program draws an octagon. How can i fill in the missing parts?

current result

import scipy.interpolate
import numpy
import matplotlib 
import matplotlib.pyplot as plt
import math

# close old plots
plt.close("all")

# some parameters
xy_center = [2,2]   # center of the plot
radius = 2          # radius

# mostly original code
meanR = [33.9, 34.2, 33.1, 33.5, 33.,  32.7, 32.3, 31.8, 35.]

x = numpy.array([2, 2, 2+math.sqrt(2), 4, 2+math.sqrt(2), 2, 2+(-math.sqrt(2)), 0, 2+(-math.sqrt(2))])
y = numpy.array([2, 4, 2+math.sqrt(2), 2, 2+(-math.sqrt(2)), 0, 2+(-math.sqrt(2)), 2, 2+math.sqrt(2)])

z = meanR
xi, yi = numpy.mgrid[x.min():x.max():500j, y.min():y.max():500j]

zi = scipy.interpolate.griddata((x, y), z, (xi, yi), method='cubic')

# make figure
fig = plt.figure(figsize=(10, 10))

# set aspect = 1 to make it a circle
ax = fig.add_subplot(111, aspect = 1)

# use different number of levels for the fill and the lines
CS = ax.contourf(xi, yi, zi, 300, cmap=plt.cm.viridis, zorder=1)

# make a color bar
cbar = fig.colorbar(CS, ax=ax)

# add the data points
ax.scatter(x, y, marker = 'o', c = 'b', s = 15, zorder = 3)

for i in range(9):
    ax.annotate(str(z[i]), (x[i],y[i]))

# draw a circle
circle = matplotlib.patches.Circle(xy = xy_center, radius = radius, edgecolor = "k", facecolor = "none")
ax.add_patch(circle)

# remove the ticks
ax.set_xticks([])
ax.set_yticks([])

# set axes limits
ax.set_xlim(-0.5, 4.5)
ax.set_ylim(-0.5, 4.5)
plt.show() 
1 Answers

Radial basis functions (Rbf) can be used to interpolate/extrapolate your data. scipy.interpolation Here is a modified code that produces the plot you need.

import numpy as np
import matplotlib
import matplotlib.pyplot as plt
import math
from scipy.interpolate import Rbf

# some parameters
xy_center = [2,2]   # center of the plot
radius = 2          # radius

# Data part
# ---------
# mostly original code
meanR = [33.9, 34.2, 33.1, 33.5, 33., 32.7, 32.3, 31.8, 35.]  #9 points data
x = np.array([2, 2, 2+math.sqrt(2), 4, 2+math.sqrt(2), 2, 2+(-math.sqrt(2)), 0, 2+(-math.sqrt(2))])
y = np.array([2, 4, 2+math.sqrt(2), 2, 2+(-math.sqrt(2)), 0, 2+(-math.sqrt(2)), 2, 2+math.sqrt(2)])
z = meanR

# use RBF (Radial basis functions) that allows extrapolation
rbf = Rbf(x, y, z, epsilon=radius+1)  #epsilon is based on some parameters of the data

# Interpolation/extrapolation
# ---------------------------
xi, yi = np.mgrid[x.min():x.max():500j, y.min():y.max():500j]
# applies and get inter/extra-polated values
zi = rbf(xi, yi)

# make zi outside circle --> np.none
midr,midc = zi.shape[0]/2, zi.shape[1]/2
for er in range(zi.shape[0]):
    for ec in range(zi.shape[1]):
        if np.abs(math.sqrt((er-midr)**2 + (ec-midc)**2))>zi.shape[0]/2:
            # outside the circle, dont plot this pixel
            zi[er][ec] = np.nan
        pass
    pass

# make figure
fig = plt.figure(figsize=(8, 8))

# set aspect = 1 to make it a circle
ax = fig.add_subplot(111, aspect = 1)

# add the data points
ax.scatter(x, y, marker = 'o', c = 'b', s = 15, zorder = 3)

for i in range(9):
    ax.annotate(str(z[i]), (x[i],y[i]))

# draw a circle
circle = matplotlib.patches.Circle(xy = xy_center, radius = radius, edgecolor = "k", facecolor = "none")
ax.add_patch(circle)

CS = ax.contourf(xi, yi, zi, 300, cmap=plt.cm.viridis, zorder=1)
cbar = fig.colorbar(CS, ax=ax, shrink=0.7) # make a color bar

# remove the ticks
ax.set_xticks([])
ax.set_yticks([])

# set axes limits
ax.set_xlim(-0.5, 4.5)
ax.set_ylim(-0.5, 4.5)
plt.show() 

The result:

enter image description here

Related