Show better representation of small values of 2D plot

Question:

I am trying to make a 2D plot of a function 1/(xy) but the y values vary from 3 orders of magnitude which makes the graph look unreadable. On top of that, I am trying to emphasize the small values of 1/(xy) i.e. when x and y are big.

Here is my linear attempt:

import matplotlib.pyplot as plt
import numpy as np


x = np.linspace(0.1,0.8,100)
y = np.linspace(100e-3, 110,100)
X,Y = np.meshgrid(x, y) # grid of point
Z =1/(gamma*X*Y)
print(Y.shape)

dx = (x[1]-x[0])/2.
dy = (y[1]-y[0])/2.
extent = [x[0]-dx, x[-1]+dx, y[0]-dy, y[-1]+dy]



plt.imshow(Z, origin='lower',extent=extent, aspect='auto', norm=LogNorm())
clb = plt.colorbar()
plt.xlabel('G/('+r'$mathrm{mu}$'+r'T)')
plt.ylabel('T_2 ('+r'$mathrm{mu}$'+r's)')
plt.scatter(0.7,104)
plt.scatter(0.33, 100e-3)
plt.show()

You see two points on both extremes but from this graph one cannot really gauge the different. So I tried log scaling the y axis:

import matplotlib.pyplot as plt
import numpy as np

x = np.linspace(0.1,0.8,100)
y = np.linspace(1e-3, 110,100)
X,Y = np.meshgrid(x, y) # grid of point
Z =1/(gamma*X*Y)
print(Y.shape)

dx = (x[1]-x[0])/2.
dy = (y[1]-y[0])/2.
extent = [x[0]-dx, x[-1]+dx, y[0]-dy, y[-1]+dy]



plt.imshow(Z, origin='lower',extent=extent, aspect='auto')
clb = plt.colorbar()
plt.xlabel('G/('+r'$mathrm{mu}$'+r'T)')
plt.ylabel('T_2 ('+r'$mathrm{mu}$'+r's)')
plt.scatter(0.7,104)
plt.scatter(0.33,500e-3)
plt.yscale('log')
plt.show()

But it still doesn’t give readable results. Most importantly it seems anything below a certain value is deemed zero hence the entire dark purple area. But this area and the changes here are what I want to see most. It seems the drastic changes to 1/(smallnumber*smallnumber) are changing the possibility of seeing good results.

Any insight is appreciated.

Asked By: mikanim

||

Answers:

What about using the broken axis feature available in the matplotlib library?

You did not provide a value for gamma so I set it to 0.1.

The set_ylim allows to highlight the parts of interest of your image.

import matplotlib.pyplot as plt
from matplotlib.colors import LogNorm
import numpy as np


x = np.linspace(0.1,0.8,100)
y = np.linspace(100e-3, 110,100)
X,Y = np.meshgrid(x, y)
gamma=0.1
Z =1/(gamma*X*Y)

dx = (x[1]-x[0])/2.
dy = (y[1]-y[0])/2.
extent = [x[0]-dx, x[-1]+dx, y[0]-dy, y[-1]+dy]

fig, (ax1, ax2) = plt.subplots(2, 1)
fig.subplots_adjust(hspace=0.07)

im = ax1.imshow(Z, origin='lower',extent=extent, aspect='auto', norm=LogNorm())
ax2.imshow(Z, origin='lower',extent=extent, aspect='auto', norm=LogNorm())

ax1.scatter(0.7,104)
ax2.scatter(0.33, 100e-3, c='r')

ax1.set_ylim(100, 110)
ax2.set_ylim(0, 0.2)

cbar_ax = fig.add_axes([0.92, 0.15, 0.02, 0.7])
fig.colorbar(im, cax=cbar_ax)

ax1.spines.bottom.set_visible(False)
ax2.spines.top.set_visible(False)
ax1.xaxis.tick_top()
ax1.tick_params(labeltop=False)
ax2.xaxis.tick_bottom()

d = .5
kwargs = dict(marker=[(-1, -d), (1, d)], markersize=12,
              linestyle="none", color='k', mec='k', mew=1, clip_on=False)
ax1.plot([0, 1], [0, 0], transform=ax1.transAxes, **kwargs)
ax2.plot([0, 1], [1, 1], transform=ax2.transAxes, **kwargs)

plt.show()

enter image description here

Answered By: blunova

I worked on this and this gave me the best results:

import matplotlib.pyplot as plt
import numpy as np
from matplotlib.colors import LogNorm

x = np.linspace(0.1,0.8,100)
y = np.geomspace(1e-3, 110,100)
X,Y = np.meshgrid(x, y) # grid of point
gamma = 2.8e6
Z =1/(gamma*X*Y)

plt.pcolormesh(X,Y,Z, shading='auto', norm=LogNorm())
clb = plt.colorbar()
clabel = 'Spatial resolution [m]'
clb.set_label(clabel)

plt.xlabel('Gradient [G/'+r'$mathrm{mu}$'+r'm]')
plt.ylabel(''+r'$T_2$'+r' ['+r'$mathrm{mu}$'+r's]')
plt.scatter(0.7,104)
plt.scatter(0.33,500e-3)
plt.yscale('log')
plt.show()
plt.savefig('spatres0.png')

enter image description here

Answered By: mikanim
Categories: questions Tags: , , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.