1

I am trying make some contours to my special data. I am using matplotlib contour and SciPy griddata routines for this. But the lines of contours are obtained very detailed and too fragmented. I want to achieve a more coarse distribution. My minimized python code as follows.

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib.ticker as ticker
from scipy.interpolate import griddata
import matplotlib.cm as cm
from matplotlib.colors import LinearSegmentedColormap

data = np.array([
    [-1.685, 0.588, 1.779], [ 2.526, 0.486, 1.704], [ 1.073, 1.434, 1.774],
    [ 0.368,-0.209, 1.777], [ 0.741, 0.416, 1.772], [-0.637,-0.141, 1.698],
    [-0.834,-0.772, 1.754], [ 0.003, 1.534, 1.818], [ 2.950, 0.464, 1.603],
    [-2.615, 0.111, 1.867], [-1.282, 0.159, 1.848], [ 0.928, 1.284, 1.700],
    [-1.574, 0.198, 1.867], [ 2.583,-0.289, 1.808], [-2.102, 0.661, 1.978],
    [ 1.905,-0.601, 1.859], [ 1.226,-0.069, 1.847], [-1.524, 0.629, 2.008],
    [-0.242,-0.197, 1.794], [-1.245, 0.616, 1.754], [-1.474, 0.468, 1.908],
    [ 1.213,-0.962, 1.713], [-0.462, 0.469, 1.854], [-0.872,-0.127, 1.824],
    [-0.280, 0.723, 1.783], [-0.325, 0.749, 1.853], [-1.617, 0.056, 1.924],
    [-1.682, 0.731, 1.863], [-1.034,-0.469, 1.706], [ 0.42, -0.291, 1.905],
    [ 0.276, 1.124, 1.843], [ 2.938, 0.724, 1.581], [ 0.67, -0.299, 1.796],
    [-2.222,-0.584, 1.752], [-2.047,-0.441, 1.668], [-0.162, 0.054, 1.650],
    [-0.342,-0.649, 1.776], [-0.557,-0.591, 1.816], [-0.157, 0.103, 1.863],
    [ 0.803,-0.562, 1.706], [-0.607, 0.539, 1.824], [ 1.576, 0.298, 1.826],
    [-0.259,-0.597, 1.825], [ 1.12,  1.863, 1.698], [-0.95,  0.258, 1.778],
    [ 1.623, 1.468, 1.592], [-1.619,-0.019, 1.706], [-2.744,-0.701, 1.973],
    [ 0.373, 0.096, 1.609], [-1.049, 0.774, 1.674], [ 2.598, 0.079, 1.704],
    [ 1.028, 0.994, 1.708], [-0.012,-0.799, 1.816], [-1.544, 0.159, 1.752],
    [-0.982,-0.034, 1.686], [-2.18,  1.319, 1.924], [ 0.473, 0.444, 1.625],
    [-0.39,  1.279, 2.014], [-1.659,-0.734, 2.060], [ 0.423, 0.358, 1.762],
    [-0.879, 0.168, 1.640]
    ])


fig, ax = plt.subplots(nrows=1, ncols=1, figsize=(8.09,3.92))
fig.subplots_adjust(left=0.093, bottom=0.135, right=0.982, top=0.975, hspace=0.0, wspace=0.0)

ax.set_xlim(-3.0, 3.0)
ax.set_ylim(-1.0, 2.0)
ax.set_xlabel(r'$\Delta\alpha (^{\prime})$')
ax.set_ylabel(r'$\Delta\delta (^{\prime})$')
ax.invert_xaxis()

ax.minorticks_on()
ax.xaxis.set_major_locator(ticker.MultipleLocator(1))
ax.xaxis.set_minor_locator(ticker.AutoMinorLocator(1))
ax.yaxis.set_major_locator(ticker.MultipleLocator(0.4))
ax.yaxis.set_minor_locator(ticker.AutoMinorLocator(2))

ax.tick_params(axis="both", direction='in',which='major', length=5, top=True, right=True)
ax.tick_params(axis="both", direction='in',which='minor', length=3, top=True, right=True)
ax.axvline(x=0, color='k', linestyle='--', dashes=(7, 5), linewidth=0.6)
ax.axhline(y=0, color='k', linestyle='--', dashes=(7, 5), linewidth=0.6)

x = data[:,0]
y = data[:,1]
z = data[:,2]

ax.scatter(x, y, s=5, c='r')       # x,y data

xi, yi = np.mgrid[-3.0:3.0:20j, -1.0:2.0:10j]
zi = griddata((x,y), z, (xi,yi), method='cubic')        # make grid data

contour_labels = ax.contour(xi, yi, zi, levels=[1.6, 1.7, 1.75, 1.8], colors='k', linewidths=0.8)
ax.clabel(contour_labels, fmt='%1.2f', colors='k', fontsize=8, inline=True, inline_spacing=0)

plt.show()

This code gives me a figure like that Figure obtained

Is it possible to obtain a figure below (This was produced in the Grapher of Golden Software) wanted figure

How can I produce this figure? Is there a way to make this in python?

Bluerose
  • 131
  • 1
  • 13
  • Does this answer your question? [How to smooth matplotlib contour plot?](https://stackoverflow.com/questions/12274529/how-to-smooth-matplotlib-contour-plot) – JohanC Jul 18 '20 at 14:44
  • You just need more points in your mesh: `xi, yi = np.mgrid[-3.0:3.0:60j, -1.0:2.0:30j]` – JohanC Jul 18 '20 at 15:00
  • @JohanC I tried this option and obtained more smooth result. But the appearance of figure does not change. – Bluerose Jul 19 '20 at 10:53

2 Answers2

0

Use scipy.ndimage.zoom to smooth out the gridded data and plot. Here is the relevant code and sample plot:-

...
# require ndimage
from scipy import ndimage

...
# use `nearest` in stead of others
zi = griddata((x,y), z, (xi,yi), method='nearest') 

# resample your data grid by a factor of 4 using cubic spline interpolation
pw = 4
xm = ndimage.zoom(xi, pw)
ym = ndimage.zoom(yi, pw)
zm = ndimage.zoom(zi, pw)
contour_labels = plt.contour(xm, ym, zm, levels=[1.6, 1.7, 1.75, 1.8], colors='k', linewidths=0.8)
ax.clabel(contour_labels, fmt='%1.2f', colors='k', fontsize=8, inline=True, inline_spacing=0)

plt.show()

The output plot:

enter image description here

swatchai
  • 17,400
  • 3
  • 39
  • 58
0

With the help of @swatchai approximation, I changed some parameters and obtained an acceptable result. I changed the line

xi, yi = np.mgrid[-3.0:3.0:20j, -1.0:2.0:10j]

to this line

xi, yi = np.mgrid[-3.0:3.0:6j, -1.0:2.0:4j]

and re-written some lines of code as

zi = griddata((x,y), z, (xi,yi), method='nearest')

pw = 8.
xm = zoom(xi, pw)
ym = zoom(yi, pw)
zm = zoom(zi, pw)

seclvls = [1.6, 1.7, 1.75, 1.8]

contour_labels = ax.contour(xm, ym, zm, levels=seclvls, linewidths=0.8, colors='k')

As a result of these changes, I obtained this figure.

final image

Although I did not have the exact result I wanted, this can be an acceptable result.

Bluerose
  • 131
  • 1
  • 13
  • Also here you can increase the zoom factor, e.g. `pw=20` to obtain a smoother image. – JohanC Jul 19 '20 at 11:36
  • Note that this approach first maps your data to a grid of 24 points. This will ignore many of the original given heights; it only takes into account the original data that happens to be close to a grid point. – JohanC Jul 19 '20 at 11:41
  • I tried pw = 20 option to get smooth curve. For coarse approximation, this will be enough solution. Of course some points of the data will be ignored in order to make a coarse approximation. – Bluerose Jul 19 '20 at 13:03